@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,81 @@
1
+ import { OutboundPolicy, PendingMessages, type OutboundCaller } from "./outbound.js";
2
+ /** Which organisation a placed call belongs to. Operator configuration only. */
3
+ export declare const TENANT_ENV = "STANDIN_TENANT_ID";
4
+ /**
5
+ * Something that can say a line on a call that is already up.
6
+ *
7
+ * Implemented by the plugin, because only it knows how to make its provider
8
+ * speak without stepping on whatever the agent was already saying.
9
+ */
10
+ export interface LiveSpeaker {
11
+ say(text: string): Promise<void>;
12
+ }
13
+ /**
14
+ * Which calls are up, and how to speak into them.
15
+ *
16
+ * A call is filed under its own id and, when it has one, under the Microsoft
17
+ * Teams conversation it belongs to. Both, because a delivery addressed by
18
+ * conversation would otherwise miss a call that is only filed by call id, and
19
+ * the agent would place a second call to somebody already on the line with it.
20
+ */
21
+ export declare class LiveCalls {
22
+ #private;
23
+ register(speaker: LiveSpeaker, callId: string, threadId?: string): void;
24
+ /**
25
+ * Remove this speaker's keys, and only this speaker's.
26
+ *
27
+ * The identity check is the point. A second call on the same thread can start
28
+ * before the first one's teardown runs, and a blind delete would then wipe
29
+ * the live call's entry: every later delivery for that thread would ring a
30
+ * fresh call, and the person would hear a second ring instead of an answer.
31
+ */
32
+ unregister(speaker: LiveSpeaker, callId: string, threadId?: string): void;
33
+ /** The first live call any of these keys names. Conversation first. */
34
+ find(...keys: string[]): LiveSpeaker | undefined;
35
+ get size(): number;
36
+ }
37
+ /** What happened to one line of text. */
38
+ export interface Delivery {
39
+ readonly ok: boolean;
40
+ /**
41
+ * `"live-call"` when it was spoken into a call that was already up, or
42
+ * `"call-back"` when a call was placed and the line parked for the answer.
43
+ * Both strings are part of this API.
44
+ */
45
+ readonly mode?: "live-call" | "call-back";
46
+ /** The call that was placed, on the call-back path. */
47
+ readonly callId?: string;
48
+ /** One sentence, safe to read out loud. Absent when ok. */
49
+ readonly error?: string;
50
+ }
51
+ /** Options for {@link VoiceDelivery}. */
52
+ export interface VoiceDeliveryOptions {
53
+ caller?: OutboundCaller;
54
+ policy?: OutboundPolicy;
55
+ pending?: PendingMessages;
56
+ /**
57
+ * The organisation to place calls into.
58
+ *
59
+ * Operator configuration only: this option, falling back to
60
+ * `STANDIN_TENANT_ID`. Never the message, the metadata, the model or the
61
+ * caller, because a model steered by whoever is talking must not be able to
62
+ * choose which organisation gets dialled.
63
+ */
64
+ tenantId?: string;
65
+ /** Directory id recorded against a parked message, for the audit trail. */
66
+ requestedBy?: string;
67
+ }
68
+ /**
69
+ * Speak into a live call if there is one, otherwise ring back.
70
+ *
71
+ * {@link deliver} never throws. Every refusal comes back as a sentence, because
72
+ * the thing reading the result is either a host that will mark the whole
73
+ * platform failed on an exception, or a model that will say it out loud.
74
+ */
75
+ export declare class VoiceDelivery {
76
+ #private;
77
+ constructor(live: LiveCalls, options?: VoiceDeliveryOptions);
78
+ /** Say this line to that person, by whichever lane can reach them. */
79
+ deliver(text: string, target?: string, threadId?: string): Promise<Delivery>;
80
+ }
81
+ //# sourceMappingURL=delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"AA2BA,OAAO,EAEL,cAAc,EACd,eAAe,EACf,KAAK,cAAc,EAEpB,MAAM,eAAe,CAAC;AAEvB,gFAAgF;AAChF,eAAO,MAAM,UAAU,sBAAsB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,qBAAa,SAAS;;IAGpB,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,IAAI;IAKnE;;;;;;;OAOG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,IAAI;IAOrE,uEAAuE;IACvE,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,GAAG,SAAS;IAQhD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED,yCAAyC;AACzC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;;gBAQZ,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,oBAAyB;IAS/D,sEAAsE;IAChE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,SAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;CAoG3E"}
@@ -0,0 +1,187 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * Getting a line of text to a person, whether or not they are already on a call.
5
+ *
6
+ * Something outside the call wants to reach somebody: a scheduled job, a chat
7
+ * message, a host handing off a task. There are two ways that can land, and
8
+ * which one is right depends entirely on whether a call to that person is up
9
+ * right now.
10
+ *
11
+ * If one is, the line should be spoken into it. Ringing somebody who is mid
12
+ * sentence with you is the rudest possible way to tell them something.
13
+ *
14
+ * If one is not, the call has to be placed, and the line parked so it is said
15
+ * the moment they answer. `outbound.ts` already has every piece of that: who
16
+ * may be rung, how often, and the durable parking. What it has never had is a
17
+ * way to reach a call that is ALREADY up, so every plugin that wanted this
18
+ * wrote its own registry, and the ones that exist disagree with each other
19
+ * about identity and about what to do when the live path fails.
20
+ *
21
+ * Nothing in this module imports a provider or a host.
22
+ *
23
+ * Identical in shape to the Python SDK's `standin.delivery`.
24
+ */
25
+ import { logger } from "./log.js";
26
+ import { OutboundError, OutboundPolicy, PendingMessages, } from "./outbound.js";
27
+ /** Which organisation a placed call belongs to. Operator configuration only. */
28
+ export const TENANT_ENV = "STANDIN_TENANT_ID";
29
+ /**
30
+ * Which calls are up, and how to speak into them.
31
+ *
32
+ * A call is filed under its own id and, when it has one, under the Microsoft
33
+ * Teams conversation it belongs to. Both, because a delivery addressed by
34
+ * conversation would otherwise miss a call that is only filed by call id, and
35
+ * the agent would place a second call to somebody already on the line with it.
36
+ */
37
+ export class LiveCalls {
38
+ #speakers = new Map();
39
+ register(speaker, callId, threadId = "") {
40
+ if (callId.trim())
41
+ this.#speakers.set(callId.trim(), speaker);
42
+ if (threadId.trim())
43
+ this.#speakers.set(threadId.trim(), speaker);
44
+ }
45
+ /**
46
+ * Remove this speaker's keys, and only this speaker's.
47
+ *
48
+ * The identity check is the point. A second call on the same thread can start
49
+ * before the first one's teardown runs, and a blind delete would then wipe
50
+ * the live call's entry: every later delivery for that thread would ring a
51
+ * fresh call, and the person would hear a second ring instead of an answer.
52
+ */
53
+ unregister(speaker, callId, threadId = "") {
54
+ for (const key of [callId.trim(), threadId.trim()]) {
55
+ if (key && this.#speakers.get(key) === speaker)
56
+ this.#speakers.delete(key);
57
+ }
58
+ }
59
+ /** The first live call any of these keys names. Conversation first. */
60
+ find(...keys) {
61
+ for (const key of keys) {
62
+ const found = key ? this.#speakers.get(key.trim()) : undefined;
63
+ if (found !== undefined)
64
+ return found;
65
+ }
66
+ return undefined;
67
+ }
68
+ get size() {
69
+ return this.#speakers.size;
70
+ }
71
+ }
72
+ /**
73
+ * Speak into a live call if there is one, otherwise ring back.
74
+ *
75
+ * {@link deliver} never throws. Every refusal comes back as a sentence, because
76
+ * the thing reading the result is either a host that will mark the whole
77
+ * platform failed on an exception, or a model that will say it out loud.
78
+ */
79
+ export class VoiceDelivery {
80
+ #live;
81
+ #caller;
82
+ #policy;
83
+ #pending;
84
+ #tenantId;
85
+ #requestedBy;
86
+ constructor(live, options = {}) {
87
+ this.#live = live;
88
+ this.#caller = options.caller;
89
+ this.#policy = options.policy ?? new OutboundPolicy({});
90
+ this.#pending = options.pending;
91
+ this.#tenantId = (options.tenantId ?? process.env[TENANT_ENV] ?? "").trim();
92
+ this.#requestedBy = options.requestedBy ?? "";
93
+ }
94
+ /** Say this line to that person, by whichever lane can reach them. */
95
+ async deliver(text, target = "", threadId = "") {
96
+ const line = (text ?? "").trim();
97
+ if (line === "") {
98
+ // Checked before the registry is even consulted: an empty message must
99
+ // never place a real phone call to a real person.
100
+ return { ok: false, error: "there was nothing to say" };
101
+ }
102
+ const speaker = this.#live.find(threadId, target);
103
+ if (speaker !== undefined) {
104
+ try {
105
+ await speaker.say(line);
106
+ return { ok: true, mode: "live-call" };
107
+ }
108
+ catch (err) {
109
+ // Falls through to the call-back rather than stopping here. A wedged
110
+ // provider socket would otherwise swallow the message with nobody
111
+ // told. The trade is deliberate: a half-spoken line can be repeated by
112
+ // the call-back, and a repeat beats silence.
113
+ logger.warn(`standin: could not speak into the live call, ringing back instead: ${String(err)}`);
114
+ }
115
+ }
116
+ return await this.#callBack(line, target, threadId);
117
+ }
118
+ async #callBack(line, target, threadId) {
119
+ if (this.#caller === undefined) {
120
+ return {
121
+ ok: false,
122
+ error: "no outbound caller is configured on this deployment",
123
+ };
124
+ }
125
+ const who = (target ?? "").trim();
126
+ try {
127
+ this.#policy.check(who);
128
+ }
129
+ catch (err) {
130
+ if (err instanceof OutboundError)
131
+ return { ok: false, error: err.message };
132
+ throw err;
133
+ }
134
+ if (this.#tenantId === "") {
135
+ return {
136
+ ok: false,
137
+ error: `no tenant is configured: set ${TENANT_ENV} to place calls`,
138
+ };
139
+ }
140
+ let callId = "";
141
+ try {
142
+ const placed = await this.#caller.placeCall({
143
+ userObjectId: who,
144
+ tenantId: this.#tenantId,
145
+ });
146
+ callId = (placed.callId ?? "").trim();
147
+ }
148
+ catch (err) {
149
+ return { ok: false, error: `could not place the call: ${String(err)}` };
150
+ }
151
+ if (callId === "")
152
+ return { ok: false, error: "the call was not placed" };
153
+ // Recorded only now. Counting the attempt instead would let a broken worker
154
+ // burn the hourly budget on calls that never rang anybody, and the next
155
+ // real delivery would be refused for an hour because of it.
156
+ this.#policy.record();
157
+ // Parked before this returns. The answering leg is a different call and can
158
+ // be answered before a later park would have run, and then the person picks
159
+ // up to silence.
160
+ const parked = {
161
+ callId,
162
+ text: line,
163
+ threadId: threadId.trim(),
164
+ requestedBy: this.#requestedBy,
165
+ tenantId: this.#tenantId,
166
+ target: who,
167
+ };
168
+ try {
169
+ // Guarded because parking writes to disk, and a full or read-only one
170
+ // would otherwise throw out of a method whose whole contract is that it
171
+ // does not. The call HAS been placed by now, so the honest answer names
172
+ // what was lost rather than pretending nothing rang.
173
+ this.#pending?.park(parked);
174
+ }
175
+ catch (err) {
176
+ logger.warn(`standin: the call was placed but the line was not parked: ${String(err)}`);
177
+ return {
178
+ ok: false,
179
+ mode: "call-back",
180
+ callId,
181
+ error: "the call was placed, but what to say could not be saved",
182
+ };
183
+ }
184
+ return { ok: true, mode: "call-back", callId };
185
+ }
186
+ }
187
+ //# sourceMappingURL=delivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../src/delivery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The half-duplex echo guard.
3
+ *
4
+ * A Microsoft Teams call is one acoustic loop. When the caller is on a speakerphone, the
5
+ * agent's own voice comes back up the caller leg loudly enough for a realtime
6
+ * model's server-side VAD to hear it as a turn - so the model answers itself,
7
+ * interrupts itself, and re-greets, with the caller silent the whole time. That
8
+ * is not a hypothetical: it is the failure this guard was written to stop.
9
+ *
10
+ * The fix is a time window rather than acoustic cancellation: while our own audio
11
+ * is still PLAYING OUT on the call, caller input below a loudness threshold is
12
+ * treated as our own echo and dropped, and anything above it is treated as a real
13
+ * barge-in and passed through.
14
+ *
15
+ * It lives in the plugin rather than the SDK core: the SDK owns the wire,
16
+ * not the room's acoustics.
17
+ */
18
+ /**
19
+ * How long after our audio finishes playing the guard stays armed. Playout is not
20
+ * instantaneous and neither is the echo path.
21
+ */
22
+ export declare const ECHO_SUPPRESSION_WINDOW_MS = 600;
23
+ /** Normalized RMS above which in-window caller input is a real barge-in, not echo. */
24
+ export declare const ECHO_BARGE_IN_RMS = 0.04;
25
+ import { pcm16Rms } from "./audio.js";
26
+ export { pcm16Rms };
27
+ /** Tunables, straight off the plugin's `realtime` config block. */
28
+ export interface EchoGuardOptions {
29
+ /** Set false to disable the guard entirely. */
30
+ suppressInputDuringPlayback?: boolean;
31
+ /** Window in ms; default {@link ECHO_SUPPRESSION_WINDOW_MS}. */
32
+ echoSuppressionWindowMs?: number;
33
+ /** Barge-in RMS gate 0..1; default {@link ECHO_BARGE_IN_RMS}. */
34
+ echoBargeInRms?: number;
35
+ /**
36
+ * False drops the loudness exception and suppresses ALL in-window input.
37
+ *
38
+ * Used until the caller's first real turn. On a speakerphone the opening
39
+ * greeting echoes back loud enough to clear the barge-in RMS, so allowing
40
+ * barge-in from the first frame is exactly what starts the echo loop. Once the
41
+ * caller has genuinely spoken once, normal RMS barge-in resumes for the rest of
42
+ * the call.
43
+ */
44
+ allowBargeIn?: boolean;
45
+ }
46
+ /**
47
+ * True when this frame of caller audio should be withheld from the model.
48
+ *
49
+ * `playbackActiveUntil` is the estimated epoch-ms at which the audio we have
50
+ * already sent finishes PLAYING - not the time we last sent a chunk. A realtime
51
+ * model generates faster than realtime, so send-time and play-time diverge by
52
+ * seconds on a long answer, and a guard keyed on send-time disarms in the middle
53
+ * of the sentence it is supposed to cover.
54
+ */
55
+ export declare function shouldSuppressEcho(pcm16k: Buffer, playbackActiveUntil: number, opts?: EchoGuardOptions): boolean;
56
+ //# sourceMappingURL=echoGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echoGuard.d.ts","sourceRoot":"","sources":["../src/echoGuard.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,sFAAsF;AACtF,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAKtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,gEAAgE;IAChE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,MAAM,EAC3B,IAAI,CAAC,EAAE,gBAAgB,GACtB,OAAO,CAgBT"}
@@ -0,0 +1,57 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * The half-duplex echo guard.
5
+ *
6
+ * A Microsoft Teams call is one acoustic loop. When the caller is on a speakerphone, the
7
+ * agent's own voice comes back up the caller leg loudly enough for a realtime
8
+ * model's server-side VAD to hear it as a turn - so the model answers itself,
9
+ * interrupts itself, and re-greets, with the caller silent the whole time. That
10
+ * is not a hypothetical: it is the failure this guard was written to stop.
11
+ *
12
+ * The fix is a time window rather than acoustic cancellation: while our own audio
13
+ * is still PLAYING OUT on the call, caller input below a loudness threshold is
14
+ * treated as our own echo and dropped, and anything above it is treated as a real
15
+ * barge-in and passed through.
16
+ *
17
+ * It lives in the plugin rather than the SDK core: the SDK owns the wire,
18
+ * not the room's acoustics.
19
+ */
20
+ /**
21
+ * How long after our audio finishes playing the guard stays armed. Playout is not
22
+ * instantaneous and neither is the echo path.
23
+ */
24
+ export const ECHO_SUPPRESSION_WINDOW_MS = 600;
25
+ /** Normalized RMS above which in-window caller input is a real barge-in, not echo. */
26
+ export const ECHO_BARGE_IN_RMS = 0.04;
27
+ // The one definition lives in the SDK's core audio module, because an echo
28
+ // guard, a barge-in check and a voice segmenter all want it. Imported for use
29
+ // below and re-exported so this module keeps its historical surface.
30
+ import { pcm16Rms } from "./audio.js";
31
+ export { pcm16Rms };
32
+ /**
33
+ * True when this frame of caller audio should be withheld from the model.
34
+ *
35
+ * `playbackActiveUntil` is the estimated epoch-ms at which the audio we have
36
+ * already sent finishes PLAYING - not the time we last sent a chunk. A realtime
37
+ * model generates faster than realtime, so send-time and play-time diverge by
38
+ * seconds on a long answer, and a guard keyed on send-time disarms in the middle
39
+ * of the sentence it is supposed to cover.
40
+ */
41
+ export function shouldSuppressEcho(pcm16k, playbackActiveUntil, opts) {
42
+ if (opts?.suppressInputDuringPlayback === false) {
43
+ return false;
44
+ }
45
+ const inPlaybackWindow = Date.now() <
46
+ playbackActiveUntil +
47
+ (opts?.echoSuppressionWindowMs ?? ECHO_SUPPRESSION_WINDOW_MS);
48
+ if (!inPlaybackWindow) {
49
+ return false;
50
+ }
51
+ // Before the caller's first real turn, every in-window frame is echo.
52
+ if (opts?.allowBargeIn === false) {
53
+ return true;
54
+ }
55
+ return pcm16Rms(pcm16k) < (opts?.echoBargeInRms ?? ECHO_BARGE_IN_RMS);
56
+ }
57
+ //# sourceMappingURL=echoGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echoGuard.js","sourceRoot":"","sources":["../src/echoGuard.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAE9C,sFAAsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,2EAA2E;AAC3E,8EAA8E;AAC9E,qEAAqE;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAsBpB;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAc,EACd,mBAA2B,EAC3B,IAAuB;IAEvB,IAAI,IAAI,EAAE,2BAA2B,KAAK,KAAK,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,gBAAgB,GACpB,IAAI,CAAC,GAAG,EAAE;QACV,mBAAmB;YACjB,CAAC,IAAI,EAAE,uBAAuB,IAAI,0BAA0B,CAAC,CAAC;IAClE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,sEAAsE;IACtE,IAAI,IAAI,EAAE,YAAY,KAAK,KAAK,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,IAAI,iBAAiB,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Every error this SDK raises. Mirrors the Python SDK's `StandInError`. */
2
+ export declare class StandInError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA,4EAA4E;AAC5E,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B"}
package/dist/errors.js ADDED
@@ -0,0 +1,10 @@
1
+ // Copyright (c) 2026 Komaa DigiTech
2
+ // SPDX-License-Identifier: MIT
3
+ /** Every error this SDK raises. Mirrors the Python SDK's `StandInError`. */
4
+ export class StandInError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "StandInError";
8
+ }
9
+ }
10
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B,4EAA4E;AAC5E,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ /** Resolves a hostname to addresses. Replaceable so tests can drive a rebind. */
2
+ export type LookupFn = (hostname: string, opts: {
3
+ all: true;
4
+ verbatim: true;
5
+ }) => Promise<Array<{
6
+ address: string;
7
+ family: number;
8
+ }>>;
9
+ /** Decides whether an address may be fetched. Replaceable for tests. */
10
+ export type ForbiddenIpFn = (ip: string) => boolean;
11
+ /** True for any IPv4 address that must never be fetched server-side. */
12
+ export declare function isForbiddenIpv4(ip: string): boolean;
13
+ /** True for any IPv6 address that must never be fetched server-side. */
14
+ export declare function isForbiddenIpv6(ip: string): boolean;
15
+ /**
16
+ * True for any address that must never be fetched server-side.
17
+ *
18
+ * Unparseable input is forbidden too: something that is not an address cannot be
19
+ * proven safe, and failing closed is the only correct direction here.
20
+ */
21
+ export declare function isForbiddenIp(ip: string): boolean;
22
+ /**
23
+ * Check a URL is safe to fetch, or throw saying why.
24
+ *
25
+ * http and https only, no embedded credentials, and every address the host
26
+ * resolves to must be public.
27
+ */
28
+ export declare function assertPublicHttpUrl(raw: string, lookupFn?: LookupFn, isForbiddenFn?: ForbiddenIpFn): Promise<URL>;
29
+ /**
30
+ * Fetch an image from an untrusted URL.
31
+ *
32
+ * Bounded in every direction that matters: total time, declared length, streamed
33
+ * length, and one redirect hop. Throws for anything that fails, so a caller can
34
+ * hand the reason straight back to the agent that supplied the URL.
35
+ */
36
+ export declare function fetchPublicImage(rawUrl: string, maxBytes: number, timeoutMs?: number, lookupFn?: LookupFn, isForbiddenFn?: ForbiddenIpFn, redirectsLeft?: number): Promise<{
37
+ bytes: Buffer;
38
+ mime: string;
39
+ }>;
40
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAiCA,iFAAiF;AACjF,MAAM,MAAM,QAAQ,GAAG,CACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,KAChC,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEzD,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;AAepD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAcnD;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAsBnD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAA6B,EACvC,aAAa,GAAE,aAA6B,GAC3C,OAAO,CAAC,GAAG,CAAC,CAoCd;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAS,EAClB,QAAQ,GAAE,QAA6B,EACvC,aAAa,GAAE,aAA6B,EAC5C,aAAa,SAAI,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA6I1C"}