@komaa/standin-sdk 0.1.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.
Files changed (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/dist/ambient.d.ts +80 -0
  4. package/dist/ambient.d.ts.map +1 -0
  5. package/dist/ambient.js +281 -0
  6. package/dist/ambient.js.map +1 -0
  7. package/dist/attachments.d.ts +149 -0
  8. package/dist/attachments.d.ts.map +1 -0
  9. package/dist/attachments.js +451 -0
  10. package/dist/attachments.js.map +1 -0
  11. package/dist/audio.d.ts +80 -0
  12. package/dist/audio.d.ts.map +1 -0
  13. package/dist/audio.js +170 -0
  14. package/dist/audio.js.map +1 -0
  15. package/dist/avatar.d.ts +111 -0
  16. package/dist/avatar.d.ts.map +1 -0
  17. package/dist/avatar.js +201 -0
  18. package/dist/avatar.js.map +1 -0
  19. package/dist/callServer.d.ts +151 -0
  20. package/dist/callServer.d.ts.map +1 -0
  21. package/dist/callServer.js +1097 -0
  22. package/dist/callServer.js.map +1 -0
  23. package/dist/callTools.d.ts +154 -0
  24. package/dist/callTools.d.ts.map +1 -0
  25. package/dist/callTools.js +255 -0
  26. package/dist/callTools.js.map +1 -0
  27. package/dist/chat.d.ts +226 -0
  28. package/dist/chat.d.ts.map +1 -0
  29. package/dist/chat.js +574 -0
  30. package/dist/chat.js.map +1 -0
  31. package/dist/config.d.ts +32 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +86 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/consult.d.ts +147 -0
  36. package/dist/consult.d.ts.map +1 -0
  37. package/dist/consult.js +388 -0
  38. package/dist/consult.js.map +1 -0
  39. package/dist/delivery.d.ts +81 -0
  40. package/dist/delivery.d.ts.map +1 -0
  41. package/dist/delivery.js +187 -0
  42. package/dist/delivery.js.map +1 -0
  43. package/dist/echoGuard.d.ts +56 -0
  44. package/dist/echoGuard.d.ts.map +1 -0
  45. package/dist/echoGuard.js +57 -0
  46. package/dist/echoGuard.js.map +1 -0
  47. package/dist/errors.d.ts +5 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +10 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/fetch.d.ts +40 -0
  52. package/dist/fetch.d.ts.map +1 -0
  53. package/dist/fetch.js +240 -0
  54. package/dist/fetch.js.map +1 -0
  55. package/dist/gate.d.ts +80 -0
  56. package/dist/gate.d.ts.map +1 -0
  57. package/dist/gate.js +249 -0
  58. package/dist/gate.js.map +1 -0
  59. package/dist/handler.d.ts +283 -0
  60. package/dist/handler.d.ts.map +1 -0
  61. package/dist/handler.js +4 -0
  62. package/dist/handler.js.map +1 -0
  63. package/dist/hmac.d.ts +32 -0
  64. package/dist/hmac.d.ts.map +1 -0
  65. package/dist/hmac.js +108 -0
  66. package/dist/hmac.js.map +1 -0
  67. package/dist/index.d.ts +59 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +60 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/lane.d.ts +92 -0
  72. package/dist/lane.d.ts.map +1 -0
  73. package/dist/lane.js +269 -0
  74. package/dist/lane.js.map +1 -0
  75. package/dist/lipsync.d.ts +136 -0
  76. package/dist/lipsync.d.ts.map +1 -0
  77. package/dist/lipsync.js +310 -0
  78. package/dist/lipsync.js.map +1 -0
  79. package/dist/log.d.ts +18 -0
  80. package/dist/log.d.ts.map +1 -0
  81. package/dist/log.js +20 -0
  82. package/dist/log.js.map +1 -0
  83. package/dist/media.d.ts +43 -0
  84. package/dist/media.d.ts.map +1 -0
  85. package/dist/media.js +190 -0
  86. package/dist/media.js.map +1 -0
  87. package/dist/minutes.d.ts +398 -0
  88. package/dist/minutes.d.ts.map +1 -0
  89. package/dist/minutes.js +805 -0
  90. package/dist/minutes.js.map +1 -0
  91. package/dist/outbound.d.ts +388 -0
  92. package/dist/outbound.d.ts.map +1 -0
  93. package/dist/outbound.js +933 -0
  94. package/dist/outbound.js.map +1 -0
  95. package/dist/plugins/cartesia/agent.d.ts +58 -0
  96. package/dist/plugins/cartesia/agent.d.ts.map +1 -0
  97. package/dist/plugins/cartesia/agent.js +254 -0
  98. package/dist/plugins/cartesia/agent.js.map +1 -0
  99. package/dist/plugins/cartesia/cli.d.ts +3 -0
  100. package/dist/plugins/cartesia/cli.d.ts.map +1 -0
  101. package/dist/plugins/cartesia/cli.js +10 -0
  102. package/dist/plugins/cartesia/cli.js.map +1 -0
  103. package/dist/plugins/cartesia/config.d.ts +30 -0
  104. package/dist/plugins/cartesia/config.d.ts.map +1 -0
  105. package/dist/plugins/cartesia/config.js +29 -0
  106. package/dist/plugins/cartesia/config.js.map +1 -0
  107. package/dist/plugins/cartesia/handler.d.ts +40 -0
  108. package/dist/plugins/cartesia/handler.d.ts.map +1 -0
  109. package/dist/plugins/cartesia/handler.js +142 -0
  110. package/dist/plugins/cartesia/handler.js.map +1 -0
  111. package/dist/plugins/cartesia/index.d.ts +6 -0
  112. package/dist/plugins/cartesia/index.d.ts.map +1 -0
  113. package/dist/plugins/cartesia/index.js +54 -0
  114. package/dist/plugins/cartesia/index.js.map +1 -0
  115. package/dist/plugins/deepgram/agent.d.ts +60 -0
  116. package/dist/plugins/deepgram/agent.d.ts.map +1 -0
  117. package/dist/plugins/deepgram/agent.js +302 -0
  118. package/dist/plugins/deepgram/agent.js.map +1 -0
  119. package/dist/plugins/deepgram/cli.d.ts +3 -0
  120. package/dist/plugins/deepgram/cli.d.ts.map +1 -0
  121. package/dist/plugins/deepgram/cli.js +10 -0
  122. package/dist/plugins/deepgram/cli.js.map +1 -0
  123. package/dist/plugins/deepgram/config.d.ts +39 -0
  124. package/dist/plugins/deepgram/config.d.ts.map +1 -0
  125. package/dist/plugins/deepgram/config.js +66 -0
  126. package/dist/plugins/deepgram/config.js.map +1 -0
  127. package/dist/plugins/deepgram/handler.d.ts +87 -0
  128. package/dist/plugins/deepgram/handler.d.ts.map +1 -0
  129. package/dist/plugins/deepgram/handler.js +268 -0
  130. package/dist/plugins/deepgram/handler.js.map +1 -0
  131. package/dist/plugins/deepgram/index.d.ts +11 -0
  132. package/dist/plugins/deepgram/index.d.ts.map +1 -0
  133. package/dist/plugins/deepgram/index.js +76 -0
  134. package/dist/plugins/deepgram/index.js.map +1 -0
  135. package/dist/plugins/echo/cli.d.ts +3 -0
  136. package/dist/plugins/echo/cli.d.ts.map +1 -0
  137. package/dist/plugins/echo/cli.js +10 -0
  138. package/dist/plugins/echo/cli.js.map +1 -0
  139. package/dist/plugins/echo/index.d.ts +37 -0
  140. package/dist/plugins/echo/index.d.ts.map +1 -0
  141. package/dist/plugins/echo/index.js +61 -0
  142. package/dist/plugins/echo/index.js.map +1 -0
  143. package/dist/plugins/elevenlabs/agent.d.ts +72 -0
  144. package/dist/plugins/elevenlabs/agent.d.ts.map +1 -0
  145. package/dist/plugins/elevenlabs/agent.js +305 -0
  146. package/dist/plugins/elevenlabs/agent.js.map +1 -0
  147. package/dist/plugins/elevenlabs/cli.d.ts +3 -0
  148. package/dist/plugins/elevenlabs/cli.d.ts.map +1 -0
  149. package/dist/plugins/elevenlabs/cli.js +10 -0
  150. package/dist/plugins/elevenlabs/cli.js.map +1 -0
  151. package/dist/plugins/elevenlabs/config.d.ts +27 -0
  152. package/dist/plugins/elevenlabs/config.d.ts.map +1 -0
  153. package/dist/plugins/elevenlabs/config.js +42 -0
  154. package/dist/plugins/elevenlabs/config.js.map +1 -0
  155. package/dist/plugins/elevenlabs/handler.d.ts +67 -0
  156. package/dist/plugins/elevenlabs/handler.d.ts.map +1 -0
  157. package/dist/plugins/elevenlabs/handler.js +419 -0
  158. package/dist/plugins/elevenlabs/handler.js.map +1 -0
  159. package/dist/plugins/elevenlabs/index.d.ts +11 -0
  160. package/dist/plugins/elevenlabs/index.d.ts.map +1 -0
  161. package/dist/plugins/elevenlabs/index.js +72 -0
  162. package/dist/plugins/elevenlabs/index.js.map +1 -0
  163. package/dist/plugins/livekit/cli.d.ts +3 -0
  164. package/dist/plugins/livekit/cli.d.ts.map +1 -0
  165. package/dist/plugins/livekit/cli.js +10 -0
  166. package/dist/plugins/livekit/cli.js.map +1 -0
  167. package/dist/plugins/livekit/config.d.ts +47 -0
  168. package/dist/plugins/livekit/config.d.ts.map +1 -0
  169. package/dist/plugins/livekit/config.js +46 -0
  170. package/dist/plugins/livekit/config.js.map +1 -0
  171. package/dist/plugins/livekit/handler.d.ts +59 -0
  172. package/dist/plugins/livekit/handler.d.ts.map +1 -0
  173. package/dist/plugins/livekit/handler.js +211 -0
  174. package/dist/plugins/livekit/handler.js.map +1 -0
  175. package/dist/plugins/livekit/index.d.ts +6 -0
  176. package/dist/plugins/livekit/index.d.ts.map +1 -0
  177. package/dist/plugins/livekit/index.js +68 -0
  178. package/dist/plugins/livekit/index.js.map +1 -0
  179. package/dist/plugins/livekit/room.d.ts +117 -0
  180. package/dist/plugins/livekit/room.d.ts.map +1 -0
  181. package/dist/plugins/livekit/room.js +449 -0
  182. package/dist/plugins/livekit/room.js.map +1 -0
  183. package/dist/plugins/openai/agent.d.ts +74 -0
  184. package/dist/plugins/openai/agent.d.ts.map +1 -0
  185. package/dist/plugins/openai/agent.js +264 -0
  186. package/dist/plugins/openai/agent.js.map +1 -0
  187. package/dist/plugins/openai/cli.d.ts +3 -0
  188. package/dist/plugins/openai/cli.d.ts.map +1 -0
  189. package/dist/plugins/openai/cli.js +10 -0
  190. package/dist/plugins/openai/cli.js.map +1 -0
  191. package/dist/plugins/openai/config.d.ts +29 -0
  192. package/dist/plugins/openai/config.d.ts.map +1 -0
  193. package/dist/plugins/openai/config.js +37 -0
  194. package/dist/plugins/openai/config.js.map +1 -0
  195. package/dist/plugins/openai/handler.d.ts +65 -0
  196. package/dist/plugins/openai/handler.d.ts.map +1 -0
  197. package/dist/plugins/openai/handler.js +297 -0
  198. package/dist/plugins/openai/handler.js.map +1 -0
  199. package/dist/plugins/openai/index.d.ts +6 -0
  200. package/dist/plugins/openai/index.d.ts.map +1 -0
  201. package/dist/plugins/openai/index.js +72 -0
  202. package/dist/plugins/openai/index.js.map +1 -0
  203. package/dist/plugins/openclaw/allowlist.d.ts +9 -0
  204. package/dist/plugins/openclaw/allowlist.d.ts.map +1 -0
  205. package/dist/plugins/openclaw/allowlist.js +11 -0
  206. package/dist/plugins/openclaw/allowlist.js.map +1 -0
  207. package/dist/plugins/openclaw/config.d.ts +50 -0
  208. package/dist/plugins/openclaw/config.d.ts.map +1 -0
  209. package/dist/plugins/openclaw/config.js +53 -0
  210. package/dist/plugins/openclaw/config.js.map +1 -0
  211. package/dist/plugins/openclaw/handler.d.ts +90 -0
  212. package/dist/plugins/openclaw/handler.d.ts.map +1 -0
  213. package/dist/plugins/openclaw/handler.js +146 -0
  214. package/dist/plugins/openclaw/handler.js.map +1 -0
  215. package/dist/plugins/openclaw/index.d.ts +55 -0
  216. package/dist/plugins/openclaw/index.d.ts.map +1 -0
  217. package/dist/plugins/openclaw/index.js +89 -0
  218. package/dist/plugins/openclaw/index.js.map +1 -0
  219. package/dist/plugins/openclaw/openclaw.plugin.json +74 -0
  220. package/dist/plugins/openclaw/package.json +14 -0
  221. package/dist/plugins/openclaw/realtime.d.ts +82 -0
  222. package/dist/plugins/openclaw/realtime.d.ts.map +1 -0
  223. package/dist/plugins/openclaw/realtime.js +238 -0
  224. package/dist/plugins/openclaw/realtime.js.map +1 -0
  225. package/dist/plugins/openclaw/runtime.d.ts +19 -0
  226. package/dist/plugins/openclaw/runtime.d.ts.map +1 -0
  227. package/dist/plugins/openclaw/runtime.js +160 -0
  228. package/dist/plugins/openclaw/runtime.js.map +1 -0
  229. package/dist/policy.d.ts +38 -0
  230. package/dist/policy.d.ts.map +1 -0
  231. package/dist/policy.js +95 -0
  232. package/dist/policy.js.map +1 -0
  233. package/dist/protocol.d.ts +44 -0
  234. package/dist/protocol.d.ts.map +1 -0
  235. package/dist/protocol.js +77 -0
  236. package/dist/protocol.js.map +1 -0
  237. package/dist/protocolRuntime.d.ts +19 -0
  238. package/dist/protocolRuntime.d.ts.map +1 -0
  239. package/dist/protocolRuntime.js +78 -0
  240. package/dist/protocolRuntime.js.map +1 -0
  241. package/dist/smoke.d.ts +65 -0
  242. package/dist/smoke.d.ts.map +1 -0
  243. package/dist/smoke.js +293 -0
  244. package/dist/smoke.js.map +1 -0
  245. package/dist/startup.d.ts +74 -0
  246. package/dist/startup.d.ts.map +1 -0
  247. package/dist/startup.js +112 -0
  248. package/dist/startup.js.map +1 -0
  249. package/dist/tile.d.ts +101 -0
  250. package/dist/tile.d.ts.map +1 -0
  251. package/dist/tile.js +195 -0
  252. package/dist/tile.js.map +1 -0
  253. package/dist/version.d.ts +2 -0
  254. package/dist/version.d.ts.map +1 -0
  255. package/dist/version.js +4 -0
  256. package/dist/version.js.map +1 -0
  257. package/dist/vision.d.ts +160 -0
  258. package/dist/vision.d.ts.map +1 -0
  259. package/dist/vision.js +301 -0
  260. package/dist/vision.js.map +1 -0
  261. package/dist/visionTools.d.ts +237 -0
  262. package/dist/visionTools.d.ts.map +1 -0
  263. package/dist/visionTools.js +578 -0
  264. package/dist/visionTools.js.map +1 -0
  265. package/dist/voice.d.ts +143 -0
  266. package/dist/voice.d.ts.map +1 -0
  267. package/dist/voice.js +403 -0
  268. package/dist/voice.js.map +1 -0
  269. package/package.json +129 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/echo/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9D;;;;;;GAMG;AACH,qBAAa,WAAW;;IAGhB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK7C;AAED,qEAAqE;AACrE,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAa3C"}
@@ -0,0 +1,61 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * The smallest StandIn plugin that answers a real Microsoft Teams call.
5
+ *
6
+ * Copy this directory to start a new plugin. It has no dependency beyond
7
+ * the SDK core and it works: call the number, talk, and hear yourself back. That
8
+ * makes it a useful thing to run before you suspect your own agent - if the echo
9
+ * answers, your secret, your tunnel and your StandIn identity are all correct.
10
+ *
11
+ * ```bash
12
+ * npm install @komaa/standin-sdk
13
+ * STANDIN_SECRET=... npx standin-echo
14
+ * ```
15
+ *
16
+ * To make it a real plugin, replace {@link EchoHandler.onCallerAudio} with
17
+ * your framework's agent loop. Everything else here is the shape every
18
+ * plugin keeps.
19
+ *
20
+ * The Python twin of this file is `standin.plugins.echo`; the two are the
21
+ * same handler with the same method names in each language's casing.
22
+ */
23
+ import { CallServer } from "../../index.js";
24
+ /**
25
+ * One instance per call. Sends the caller's own voice back to them.
26
+ *
27
+ * A handler implements only what it needs: the SDK treats every callback as
28
+ * optional, so this class defines three of the five and the other two are
29
+ * no-ops. Nothing extends anything.
30
+ */
31
+ export class EchoHandler {
32
+ #call;
33
+ async onStart(session) {
34
+ this.#call = session;
35
+ console.info(`call ${session.callId} from ${session.start.caller.displayName ?? "unknown"}`);
36
+ }
37
+ async onCallerAudio(pcm) {
38
+ // Your agent goes here. PCM16, 16 kHz, mono, little-endian - the same format
39
+ // sendAudio expects back.
40
+ await this.#call?.sendAudio(pcm);
41
+ }
42
+ async onGoodbye(text) {
43
+ // StandIn is ending the call and wants this line spoken first. A real plugin
44
+ // would interrupt the agent and say it.
45
+ console.info(`goodbye: ${text}`);
46
+ }
47
+ }
48
+ /** Answer Microsoft Teams calls until the process is interrupted. */
49
+ export async function serve() {
50
+ const server = new CallServer({ handlerFactory: () => new EchoHandler() });
51
+ await server.start();
52
+ await new Promise((resolve) => {
53
+ const stop = () => {
54
+ resolve();
55
+ };
56
+ process.once("SIGINT", stop);
57
+ process.once("SIGTERM", stop);
58
+ });
59
+ await server.aclose();
60
+ }
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/echo/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,gBAAgB,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,OAAO,WAAW;IACtB,KAAK,CAA0B;IAE/B,KAAK,CAAC,OAAO,CAAC,OAAoB;QAChC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;QACrB,OAAO,CAAC,IAAI,CACV,QAAQ,OAAO,CAAC,MAAM,SAAS,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,IAAI,SAAS,EAAE,CAC/E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAW;QAC7B,6EAA6E;QAC7E,0BAA0B;QAC1B,MAAM,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,6EAA6E;QAC7E,wCAAwC;QACxC,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;CACF;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE,EAAE,CAAC,CAAC;IAC3E,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,72 @@
1
+ import type { ElevenLabsConfig } from "./config.js";
2
+ /** A frame from ElevenLabs. Only `type` is guaranteed. */
3
+ export type AgentMessage = Record<string, unknown> & {
4
+ type: string;
5
+ };
6
+ /** The conversation_initiation_client_data that opens a call. */
7
+ export interface ConversationInit {
8
+ dynamicVariables: Record<string, string>;
9
+ firstMessage?: string;
10
+ environment?: string;
11
+ /**
12
+ * A stable per-person id, which is what ElevenLabs keys analytics and memory
13
+ * on. Pass the caller's directory id when there is one and NOTHING when there
14
+ * is not: a shared default would make every anonymous caller the same person,
15
+ * and one caller would read another's conversation memory.
16
+ */
17
+ userId?: string;
18
+ branchId?: string;
19
+ }
20
+ /** Build the message that opens a conversation. */
21
+ export declare function buildConversationInit(init: ConversationInit): Record<string, unknown>;
22
+ /** Mint a short-lived signed URL. Expires in about fifteen minutes, so never cached. */
23
+ export declare function getSignedUrl(config: ElevenLabsConfig): Promise<string>;
24
+ /**
25
+ * Upload one frame to the live conversation and return its file id.
26
+ *
27
+ * This PERSISTS the caller's screen or face with ElevenLabs, which is why the
28
+ * handler gates it on the call being recorded.
29
+ */
30
+ export declare function uploadConversationFile(config: ElevenLabsConfig, conversationId: string, data: Buffer, mime: string): Promise<string>;
31
+ /** What the relay needs from an agent connection. Tests substitute their own. */
32
+ export interface AgentPort {
33
+ readonly isOpen: boolean;
34
+ conversationId: string | undefined;
35
+ sendConversationInit(init: Record<string, unknown>): void;
36
+ sendAudioChunk(pcmBase64: string): void;
37
+ sendPong(eventId: number): void;
38
+ sendContextualUpdate(text: string): void;
39
+ sendUserMessage(text: string): void;
40
+ sendToolResult(toolCallId: string, result: string, isError?: boolean): void;
41
+ attachImage(data: Buffer, mime: string, question: string): Promise<void>;
42
+ aclose(): Promise<void>;
43
+ }
44
+ /** The socket to one ElevenLabs agent conversation. */
45
+ export declare class AgentSocket implements AgentPort {
46
+ #private;
47
+ conversationId: string | undefined;
48
+ private constructor();
49
+ /**
50
+ * Open the socket, retrying once with a fresh signed URL.
51
+ *
52
+ * Signed URLs are short-lived and minting one can fail transiently. One retry
53
+ * costs a quarter of a second and saves a caller from a dropped call because a
54
+ * URL expired between minting and connecting.
55
+ */
56
+ static connect(config: ElevenLabsConfig, onMessage: (message: AgentMessage) => void | Promise<void>, onClose: (code: number, reason: string) => void | Promise<void>): Promise<AgentSocket>;
57
+ get isOpen(): boolean;
58
+ /** Caller audio, forwarded verbatim. This message carries no `type`. */
59
+ sendAudioChunk(pcmBase64: string): void;
60
+ sendConversationInit(init: Record<string, unknown>): void;
61
+ sendPong(eventId: number): void;
62
+ /** Background context that must NOT interrupt the agent mid-sentence. */
63
+ sendContextualUpdate(text: string): void;
64
+ /** An interrupting user turn, which is how a goodbye gets spoken. */
65
+ sendUserMessage(text: string): void;
66
+ sendToolResult(toolCallId: string, result: string, isError?: boolean): void;
67
+ /** Upload a frame and inject it as a multimodal user turn. */
68
+ attachImage(data: Buffer, mime: string, question: string): Promise<void>;
69
+ /** Close the conversation. Safe to call twice. */
70
+ aclose(): Promise<void>;
71
+ }
72
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,305 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * One ElevenLabs agent conversation, as a socket.
5
+ *
6
+ * Deliberately thin: this file opens the socket, parses frames, and offers send
7
+ * helpers. What any of it MEANS to a Microsoft Teams call lives in `handler.ts`,
8
+ * so the wire and the relay can be read, and tested, one at a time.
9
+ *
10
+ * The contract that makes this plugin simple is the audio format. An agent
11
+ * configured for `pcm_16000` in both directions speaks exactly what StandIn
12
+ * speaks, so nothing here resamples anything. An agent configured for something
13
+ * else would produce a whole call of garbled audio, so it is caught at the
14
+ * metadata frame and refused.
15
+ *
16
+ * The Python twin is `standin.plugins.elevenlabs.agent`.
17
+ */
18
+ import { WebSocket } from "ws";
19
+ import { logger } from "../../log.js";
20
+ /** Bound on the REST calls and the socket open, so a hung API cannot wedge onStart. */
21
+ const REST_TIMEOUT_MS = 10_000;
22
+ /**
23
+ * ElevenLabs pings roughly every ten seconds, so a minute of silence means the
24
+ * peer is gone without a close frame.
25
+ */
26
+ const RECEIVE_TIMEOUT_MS = 60_000;
27
+ /** A stalled socket must not accumulate an unbounded queue of caller audio. */
28
+ const MAX_SEND_BUFFER_BYTES = 1024 * 1024;
29
+ /** The only audio format this plugin speaks, and what StandIn speaks. */
30
+ const REQUIRED_FORMAT = "pcm_16000";
31
+ const EXT_FOR_MIME = {
32
+ "image/jpeg": "jpg",
33
+ "image/jpg": "jpg",
34
+ "image/png": "png",
35
+ "image/webp": "webp",
36
+ "image/gif": "gif",
37
+ };
38
+ /** Build the message that opens a conversation. */
39
+ export function buildConversationInit(init) {
40
+ const message = {
41
+ type: "conversation_initiation_client_data",
42
+ dynamic_variables: init.dynamicVariables,
43
+ };
44
+ // Overrides are rejected unless the agent's own security settings allow them,
45
+ // so send one only when it was actually configured.
46
+ if (init.firstMessage) {
47
+ message.conversation_config_override = {
48
+ agent: { first_message: init.firstMessage },
49
+ };
50
+ }
51
+ if (init.environment)
52
+ message.environment = init.environment;
53
+ if (init.userId)
54
+ message.user_id = init.userId;
55
+ if (init.branchId)
56
+ message.branch_id = init.branchId;
57
+ return message;
58
+ }
59
+ async function withTimeout(promise, ms, what) {
60
+ let timer;
61
+ try {
62
+ return await Promise.race([
63
+ promise,
64
+ new Promise((_, reject) => {
65
+ timer = setTimeout(() => reject(new Error(`${what} timed out after ${ms}ms`)), ms);
66
+ timer.unref?.();
67
+ }),
68
+ ]);
69
+ }
70
+ finally {
71
+ if (timer)
72
+ clearTimeout(timer);
73
+ }
74
+ }
75
+ /** Mint a short-lived signed URL. Expires in about fifteen minutes, so never cached. */
76
+ export async function getSignedUrl(config) {
77
+ const params = new URLSearchParams({ agent_id: config.agentId });
78
+ if (config.environment)
79
+ params.set("environment", config.environment);
80
+ const url = `https://${config.host}/v1/convai/conversation/get-signed-url?${params}`;
81
+ const response = await withTimeout(fetch(url, { headers: { "xi-api-key": config.apiKey } }), REST_TIMEOUT_MS, "get-signed-url");
82
+ if (!response.ok)
83
+ throw new Error(`get-signed-url failed: HTTP ${response.status}`);
84
+ const body = (await response.json());
85
+ if (!body.signed_url)
86
+ throw new Error("get-signed-url returned no signed_url");
87
+ return body.signed_url;
88
+ }
89
+ /**
90
+ * Upload one frame to the live conversation and return its file id.
91
+ *
92
+ * This PERSISTS the caller's screen or face with ElevenLabs, which is why the
93
+ * handler gates it on the call being recorded.
94
+ */
95
+ export async function uploadConversationFile(config, conversationId, data, mime) {
96
+ const ext = EXT_FOR_MIME[mime.toLowerCase()];
97
+ if (!ext)
98
+ throw new Error(`unsupported image type for upload: ${mime}`);
99
+ const form = new FormData();
100
+ form.append("file", new Blob([new Uint8Array(data)], { type: mime }), `frame.${ext}`);
101
+ const url = `https://${config.host}/v1/convai/conversations/${encodeURIComponent(conversationId)}/files`;
102
+ const response = await withTimeout(fetch(url, {
103
+ method: "POST",
104
+ body: form,
105
+ headers: { "xi-api-key": config.apiKey },
106
+ }), REST_TIMEOUT_MS, "file upload");
107
+ if (!response.ok)
108
+ throw new Error(`file upload failed: HTTP ${response.status}`);
109
+ const body = (await response.json());
110
+ if (!body.file_id)
111
+ throw new Error("file upload returned no file_id");
112
+ return body.file_id;
113
+ }
114
+ /** The socket to one ElevenLabs agent conversation. */
115
+ export class AgentSocket {
116
+ #config;
117
+ #ws;
118
+ #idleTimer;
119
+ #pendingBytes = 0;
120
+ #dropped = 0;
121
+ #lastDropWarning = 0;
122
+ #closedByUs = false;
123
+ conversationId;
124
+ constructor(config) {
125
+ this.#config = config;
126
+ }
127
+ /**
128
+ * Open the socket, retrying once with a fresh signed URL.
129
+ *
130
+ * Signed URLs are short-lived and minting one can fail transiently. One retry
131
+ * costs a quarter of a second and saves a caller from a dropped call because a
132
+ * URL expired between minting and connecting.
133
+ */
134
+ static async connect(config, onMessage, onClose) {
135
+ const socket = new AgentSocket(config);
136
+ try {
137
+ await socket.#open();
138
+ }
139
+ catch (err) {
140
+ logger.warn(`standin: ElevenLabs connect failed (${String(err)}); retrying with a fresh URL`);
141
+ await new Promise((resolve) => setTimeout(resolve, 250));
142
+ await socket.#open();
143
+ }
144
+ socket.#listen(onMessage, onClose);
145
+ return socket;
146
+ }
147
+ async #open() {
148
+ const signedUrl = await getSignedUrl(this.#config);
149
+ const ws = new WebSocket(signedUrl, { maxPayload: 16 * 1024 * 1024 });
150
+ await withTimeout(new Promise((resolve, reject) => {
151
+ ws.once("open", resolve);
152
+ ws.once("error", reject);
153
+ }), REST_TIMEOUT_MS, "the ElevenLabs socket open");
154
+ this.#ws = ws;
155
+ }
156
+ #listen(onMessage, onClose) {
157
+ const ws = this.#ws;
158
+ if (ws === undefined)
159
+ return;
160
+ let closeReason = "";
161
+ const armIdle = () => {
162
+ if (this.#idleTimer)
163
+ clearTimeout(this.#idleTimer);
164
+ this.#idleTimer = setTimeout(() => {
165
+ closeReason = "receive-timeout";
166
+ ws.terminate();
167
+ }, RECEIVE_TIMEOUT_MS);
168
+ this.#idleTimer.unref?.();
169
+ };
170
+ armIdle();
171
+ ws.on("message", (raw) => {
172
+ armIdle();
173
+ let message;
174
+ try {
175
+ message = JSON.parse(raw.toString());
176
+ }
177
+ catch {
178
+ logger.warn("standin: ElevenLabs sent an unparseable frame; dropping");
179
+ return;
180
+ }
181
+ if (typeof message !== "object" || message === null)
182
+ return;
183
+ const typed = message;
184
+ if (typeof typed.type !== "string")
185
+ return;
186
+ if (typed.type === "conversation_initiation_metadata" &&
187
+ !this.#readMetadata(typed)) {
188
+ closeReason = "audio-format-mismatch";
189
+ void this.aclose();
190
+ return;
191
+ }
192
+ // A handler error must never escape and kill the relay for the call.
193
+ void (async () => {
194
+ try {
195
+ await onMessage(typed);
196
+ }
197
+ catch (err) {
198
+ logger.error(`standin: handling ElevenLabs ${typed.type} failed: ${String(err)}`);
199
+ }
200
+ })();
201
+ });
202
+ ws.on("close", (code, reason) => {
203
+ if (this.#idleTimer)
204
+ clearTimeout(this.#idleTimer);
205
+ void onClose(code, closeReason || reason.toString());
206
+ });
207
+ ws.on("error", (err) => {
208
+ logger.warn(`standin: the ElevenLabs socket failed: ${String(err)}`);
209
+ });
210
+ }
211
+ #readMetadata(message) {
212
+ const meta = (message.conversation_initiation_metadata_event ??
213
+ {});
214
+ if (typeof meta.conversation_id === "string")
215
+ this.conversationId = meta.conversation_id;
216
+ const formats = [
217
+ meta.agent_output_audio_format,
218
+ meta.user_input_audio_format,
219
+ ];
220
+ const wrong = formats.find((f) => typeof f === "string" && f !== REQUIRED_FORMAT);
221
+ if (wrong) {
222
+ // Refuse rather than log and carry on. The alternative is a call that
223
+ // stays up for its whole duration while the caller hears noise.
224
+ logger.error(`standin: the ElevenLabs agent audio is ${String(wrong)}, expected ${REQUIRED_FORMAT} ` +
225
+ "both ways; ending the call");
226
+ return false;
227
+ }
228
+ return true;
229
+ }
230
+ get isOpen() {
231
+ return this.#ws !== undefined && this.#ws.readyState === WebSocket.OPEN;
232
+ }
233
+ #send(message, droppable = false) {
234
+ const ws = this.#ws;
235
+ if (ws === undefined || ws.readyState !== WebSocket.OPEN)
236
+ return;
237
+ const payload = JSON.stringify(message);
238
+ if (droppable && this.#pendingBytes > MAX_SEND_BUFFER_BYTES) {
239
+ // Realtime audio is the only droppable thing here: control messages are
240
+ // tiny and load-bearing, so they always queue.
241
+ this.#dropped += 1;
242
+ const now = Date.now();
243
+ if (now - this.#lastDropWarning >= 1000) {
244
+ logger.warn(`standin: ElevenLabs send backpressure, dropped ${this.#dropped} chunk(s)`);
245
+ this.#lastDropWarning = now;
246
+ this.#dropped = 0;
247
+ }
248
+ return;
249
+ }
250
+ this.#pendingBytes += payload.length;
251
+ ws.send(payload, () => {
252
+ this.#pendingBytes -= payload.length;
253
+ });
254
+ }
255
+ /** Caller audio, forwarded verbatim. This message carries no `type`. */
256
+ sendAudioChunk(pcmBase64) {
257
+ this.#send({ user_audio_chunk: pcmBase64 }, true);
258
+ }
259
+ sendConversationInit(init) {
260
+ this.#send(init);
261
+ }
262
+ sendPong(eventId) {
263
+ this.#send({ type: "pong", event_id: eventId });
264
+ }
265
+ /** Background context that must NOT interrupt the agent mid-sentence. */
266
+ sendContextualUpdate(text) {
267
+ this.#send({ type: "contextual_update", text });
268
+ }
269
+ /** An interrupting user turn, which is how a goodbye gets spoken. */
270
+ sendUserMessage(text) {
271
+ this.#send({ type: "user_message", text });
272
+ }
273
+ sendToolResult(toolCallId, result, isError = false) {
274
+ this.#send({
275
+ type: "client_tool_result",
276
+ tool_call_id: toolCallId,
277
+ result,
278
+ is_error: isError,
279
+ });
280
+ }
281
+ /** Upload a frame and inject it as a multimodal user turn. */
282
+ async attachImage(data, mime, question) {
283
+ if (!this.conversationId)
284
+ throw new Error("the conversation has not started yet");
285
+ const fileId = await uploadConversationFile(this.#config, this.conversationId, data, mime);
286
+ this.#send({
287
+ type: "multimodal_message",
288
+ text: { type: "user_message", text: question },
289
+ file: { type: "file_input", file_id: fileId },
290
+ });
291
+ }
292
+ /** Close the conversation. Safe to call twice. */
293
+ async aclose() {
294
+ if (this.#closedByUs)
295
+ return;
296
+ this.#closedByUs = true;
297
+ if (this.#idleTimer)
298
+ clearTimeout(this.#idleTimer);
299
+ const ws = this.#ws;
300
+ if (ws !== undefined && ws.readyState === WebSocket.OPEN) {
301
+ ws.close(1000, "session-end");
302
+ }
303
+ }
304
+ }
305
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ // Copyright (c) 2026 Komaa DigiTech
3
+ // SPDX-License-Identifier: MIT
4
+ /** `npx standin-elevenlabs` */
5
+ import { serve } from "./index.js";
6
+ serve().catch((err) => {
7
+ console.error(String(err));
8
+ process.exitCode = 1;
9
+ });
10
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/cli.ts"],"names":[],"mappings":";AACA,oCAAoC;AACpC,+BAA+B;AAE/B,+BAA+B;AAE/B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC7B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /** Everything the ElevenLabs plugin needs, resolved once per worker. */
2
+ export interface ElevenLabsConfig {
3
+ /** `ELEVENLABS_API_KEY`. Never logged, never sent to StandIn. */
4
+ apiKey: string;
5
+ /** `ELEVENLABS_AGENT_ID`: which agent answers the call. */
6
+ agentId: string;
7
+ /** `ELEVENLABS_HOST`. Must be an elevenlabs.io host. */
8
+ host: string;
9
+ /** `ELEVENLABS_ENVIRONMENT`, for agents deployed to a named environment. */
10
+ environment?: string;
11
+ /**
12
+ * `ELEVENLABS_FIRST_MESSAGE` overrides the agent's opening line, and only
13
+ * when the agent's own security settings allow the override.
14
+ */
15
+ firstMessage?: string;
16
+ /** `ELEVENLABS_AGENT_BRANCH_ID`, to answer with a specific branch. */
17
+ agentBranchId?: string;
18
+ /**
19
+ * `ELEVENLABS_LOG_TRANSCRIPTS`. Off by default, and gated a second time on
20
+ * the call being recorded: a transcript in your logs is a recording of the
21
+ * caller that they did not agree to.
22
+ */
23
+ logTranscripts: boolean;
24
+ }
25
+ /** Read the configuration, or throw naming the variable that is missing. */
26
+ export declare function elevenLabsConfigFromEnv(): ElevenLabsConfig;
27
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/config.ts"],"names":[],"mappings":"AAoBA,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAeD,4EAA4E;AAC5E,wBAAgB,uBAAuB,IAAI,gBAAgB,CAiB1D"}
@@ -0,0 +1,42 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * What this plugin reads from the environment.
5
+ *
6
+ * Environment only, matching how the providers themselves expect their keys to
7
+ * arrive. Nothing is read at import: {@link elevenLabsConfigFromEnv} runs when
8
+ * you build a handler, so a worker that never uses ElevenLabs never needs an
9
+ * ElevenLabs key.
10
+ *
11
+ * One prefix, `ELEVENLABS_`. The standalone bridge this replaces had grown two,
12
+ * which is the sort of thing that survives only until somebody documents it.
13
+ */
14
+ import { StandInError } from "../../errors.js";
15
+ /** Refuse a host that is not ElevenLabs: the API key and agent id travel to it. */
16
+ const ALLOWED_HOST_SUFFIX = ".elevenlabs.io";
17
+ function required(name) {
18
+ const value = (process.env[name] ?? "").trim();
19
+ if (!value)
20
+ throw new StandInError(`${name} is required to answer calls with ElevenLabs`);
21
+ return value;
22
+ }
23
+ function optional(name) {
24
+ return (process.env[name] ?? "").trim() || undefined;
25
+ }
26
+ /** Read the configuration, or throw naming the variable that is missing. */
27
+ export function elevenLabsConfigFromEnv() {
28
+ const host = (process.env.ELEVENLABS_HOST ?? "").trim() || "api.elevenlabs.io";
29
+ if (host !== "elevenlabs.io" && !host.endsWith(ALLOWED_HOST_SUFFIX)) {
30
+ throw new StandInError(`ELEVENLABS_HOST must be an elevenlabs.io host, got ${host}`);
31
+ }
32
+ return {
33
+ apiKey: required("ELEVENLABS_API_KEY"),
34
+ agentId: required("ELEVENLABS_AGENT_ID"),
35
+ host,
36
+ environment: optional("ELEVENLABS_ENVIRONMENT"),
37
+ firstMessage: optional("ELEVENLABS_FIRST_MESSAGE"),
38
+ agentBranchId: optional("ELEVENLABS_AGENT_BRANCH_ID"),
39
+ logTranscripts: process.env.ELEVENLABS_LOG_TRANSCRIPTS === "true",
40
+ };
41
+ }
42
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/config.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,mFAAmF;AACnF,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AA2B7C,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,CAAC,KAAK;QACR,MAAM,IAAI,YAAY,CACpB,GAAG,IAAI,8CAA8C,CACtD,CAAC;IACJ,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;AACvD,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB;IACrC,MAAM,IAAI,GACR,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,mBAAmB,CAAC;IACpE,IAAI,IAAI,KAAK,eAAe,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,YAAY,CACpB,sDAAsD,IAAI,EAAE,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC;QACtC,OAAO,EAAE,QAAQ,CAAC,qBAAqB,CAAC;QACxC,IAAI;QACJ,WAAW,EAAE,QAAQ,CAAC,wBAAwB,CAAC;QAC/C,YAAY,EAAE,QAAQ,CAAC,0BAA0B,CAAC;QAClD,aAAa,EAAE,QAAQ,CAAC,4BAA4B,CAAC;QACrD,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,MAAM;KAClE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The relay: one Microsoft Teams call on one side, one ElevenLabs agent on the
3
+ * other.
4
+ *
5
+ * A plain `CallHandler`. Everything that is the same for every framework - the
6
+ * socket StandIn dials, the handshake, capacity, the frame loop, the watchdogs -
7
+ * belongs to `CallServer`, so what is left here is only what ElevenLabs needs.
8
+ *
9
+ * The client tools it answers are the SDK's call capabilities, so this agent can
10
+ * do what every other provider's can. ElevenLabs declares client tools on the
11
+ * agent rather than over the wire, so {@link clientTools} returns the exact
12
+ * declarations to paste in rather than leaving you to retype them.
13
+ *
14
+ * Two of them mean something slightly different here, and the difference is the
15
+ * reason they are not the SDK's implementations. `look` uploads the frame into
16
+ * the conversation for the model to read directly, which PERSISTS the caller's
17
+ * screen with ElevenLabs and is why it takes a recorded call. `show_image` also
18
+ * accepts inline bytes, which no other provider offers.
19
+ *
20
+ * The Python twin is `standin.plugins.elevenlabs.handler`, method for
21
+ * method.
22
+ */
23
+ import type { CallHandler, CallSession } from "../../handler.js";
24
+ import { type VideoFrame } from "../../vision.js";
25
+ import { type AgentMessage, type AgentPort } from "./agent.js";
26
+ import { type ElevenLabsConfig } from "./config.js";
27
+ /**
28
+ * The client tools to declare on the ElevenLabs agent.
29
+ *
30
+ * ElevenLabs configures tools on the agent, not over the wire, so there is
31
+ * nothing this plugin can send. What it can do is hand you the declarations
32
+ * verbatim. The names and descriptions are the SDK's, so this agent is told
33
+ * about the same capabilities as every other provider's. `show_image` is
34
+ * widened here because ElevenLabs is the one provider that can take the bytes
35
+ * inline.
36
+ */
37
+ export declare function clientTools(): Array<Record<string, unknown>>;
38
+ /** How the handler reaches ElevenLabs. Replaceable so tests need no network. */
39
+ export type Connect = (config: ElevenLabsConfig, onMessage: (message: AgentMessage) => void | Promise<void>, onClose: (code: number, reason: string) => void | Promise<void>) => Promise<AgentPort>;
40
+ /** One Microsoft Teams call answered by one ElevenLabs agent. */
41
+ export declare class ElevenLabsHandler implements CallHandler {
42
+ #private;
43
+ constructor(config?: ElevenLabsConfig, connect?: Connect);
44
+ onStart(session: CallSession): Promise<void>;
45
+ /** The caller's voice, straight through. Both sides are PCM16 at 16 kHz. */
46
+ onCallerAudio(pcm: Buffer): Promise<void>;
47
+ /**
48
+ * Keep a short history, so `look_back` has something to look at.
49
+ *
50
+ * The store itself refuses to keep anything unless the call is being
51
+ * recorded, which is the same promise `look` makes.
52
+ */
53
+ onVideoFrame(frame: VideoFrame): Promise<void>;
54
+ /**
55
+ * Participant counts, key presses, recording changes. Sent as a contextual
56
+ * update, which ElevenLabs delivers WITHOUT interrupting mid-sentence.
57
+ */
58
+ onContext(text: string): Promise<void>;
59
+ /**
60
+ * StandIn is ending the call and wants this line spoken first. Delivered as a
61
+ * user turn, which interrupts whatever the agent was saying.
62
+ */
63
+ onGoodbye(text: string): Promise<void>;
64
+ /** Close the conversation. Always runs exactly once. */
65
+ aclose(): Promise<void>;
66
+ }
67
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/plugins/elevenlabs/handler.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKjE,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB7E;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoC5D;AAED,gFAAgF;AAChF,MAAM,MAAM,OAAO,GAAG,CACpB,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC1D,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAC5D,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,iEAAiE;AACjE,qBAAa,iBAAkB,YAAW,WAAW;;gBAoBjD,MAAM,CAAC,EAAE,gBAAgB,EACzB,OAAO,GAAE,OAA+C;IAkBpD,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDlD,4EAA4E;IACtE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5C,wDAAwD;IAClD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CA4T9B"}