@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.
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/ambient.d.ts +80 -0
- package/dist/ambient.d.ts.map +1 -0
- package/dist/ambient.js +281 -0
- package/dist/ambient.js.map +1 -0
- package/dist/attachments.d.ts +149 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +451 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audio.d.ts +80 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/audio.js +170 -0
- package/dist/audio.js.map +1 -0
- package/dist/avatar.d.ts +111 -0
- package/dist/avatar.d.ts.map +1 -0
- package/dist/avatar.js +201 -0
- package/dist/avatar.js.map +1 -0
- package/dist/callServer.d.ts +151 -0
- package/dist/callServer.d.ts.map +1 -0
- package/dist/callServer.js +1097 -0
- package/dist/callServer.js.map +1 -0
- package/dist/callTools.d.ts +154 -0
- package/dist/callTools.d.ts.map +1 -0
- package/dist/callTools.js +255 -0
- package/dist/callTools.js.map +1 -0
- package/dist/chat.d.ts +226 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +574 -0
- package/dist/chat.js.map +1 -0
- package/dist/config.d.ts +32 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +86 -0
- package/dist/config.js.map +1 -0
- package/dist/consult.d.ts +147 -0
- package/dist/consult.d.ts.map +1 -0
- package/dist/consult.js +388 -0
- package/dist/consult.js.map +1 -0
- package/dist/delivery.d.ts +81 -0
- package/dist/delivery.d.ts.map +1 -0
- package/dist/delivery.js +187 -0
- package/dist/delivery.js.map +1 -0
- package/dist/echoGuard.d.ts +56 -0
- package/dist/echoGuard.d.ts.map +1 -0
- package/dist/echoGuard.js +57 -0
- package/dist/echoGuard.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +10 -0
- package/dist/errors.js.map +1 -0
- package/dist/fetch.d.ts +40 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +240 -0
- package/dist/fetch.js.map +1 -0
- package/dist/gate.d.ts +80 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +249 -0
- package/dist/gate.js.map +1 -0
- package/dist/handler.d.ts +283 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +4 -0
- package/dist/handler.js.map +1 -0
- package/dist/hmac.d.ts +32 -0
- package/dist/hmac.d.ts.map +1 -0
- package/dist/hmac.js +108 -0
- package/dist/hmac.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/lane.d.ts +92 -0
- package/dist/lane.d.ts.map +1 -0
- package/dist/lane.js +269 -0
- package/dist/lane.js.map +1 -0
- package/dist/lipsync.d.ts +136 -0
- package/dist/lipsync.d.ts.map +1 -0
- package/dist/lipsync.js +310 -0
- package/dist/lipsync.js.map +1 -0
- package/dist/log.d.ts +18 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +20 -0
- package/dist/log.js.map +1 -0
- package/dist/media.d.ts +43 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +190 -0
- package/dist/media.js.map +1 -0
- package/dist/minutes.d.ts +398 -0
- package/dist/minutes.d.ts.map +1 -0
- package/dist/minutes.js +805 -0
- package/dist/minutes.js.map +1 -0
- package/dist/outbound.d.ts +388 -0
- package/dist/outbound.d.ts.map +1 -0
- package/dist/outbound.js +933 -0
- package/dist/outbound.js.map +1 -0
- package/dist/plugins/cartesia/agent.d.ts +58 -0
- package/dist/plugins/cartesia/agent.d.ts.map +1 -0
- package/dist/plugins/cartesia/agent.js +254 -0
- package/dist/plugins/cartesia/agent.js.map +1 -0
- package/dist/plugins/cartesia/cli.d.ts +3 -0
- package/dist/plugins/cartesia/cli.d.ts.map +1 -0
- package/dist/plugins/cartesia/cli.js +10 -0
- package/dist/plugins/cartesia/cli.js.map +1 -0
- package/dist/plugins/cartesia/config.d.ts +30 -0
- package/dist/plugins/cartesia/config.d.ts.map +1 -0
- package/dist/plugins/cartesia/config.js +29 -0
- package/dist/plugins/cartesia/config.js.map +1 -0
- package/dist/plugins/cartesia/handler.d.ts +40 -0
- package/dist/plugins/cartesia/handler.d.ts.map +1 -0
- package/dist/plugins/cartesia/handler.js +142 -0
- package/dist/plugins/cartesia/handler.js.map +1 -0
- package/dist/plugins/cartesia/index.d.ts +6 -0
- package/dist/plugins/cartesia/index.d.ts.map +1 -0
- package/dist/plugins/cartesia/index.js +54 -0
- package/dist/plugins/cartesia/index.js.map +1 -0
- package/dist/plugins/deepgram/agent.d.ts +60 -0
- package/dist/plugins/deepgram/agent.d.ts.map +1 -0
- package/dist/plugins/deepgram/agent.js +302 -0
- package/dist/plugins/deepgram/agent.js.map +1 -0
- package/dist/plugins/deepgram/cli.d.ts +3 -0
- package/dist/plugins/deepgram/cli.d.ts.map +1 -0
- package/dist/plugins/deepgram/cli.js +10 -0
- package/dist/plugins/deepgram/cli.js.map +1 -0
- package/dist/plugins/deepgram/config.d.ts +39 -0
- package/dist/plugins/deepgram/config.d.ts.map +1 -0
- package/dist/plugins/deepgram/config.js +66 -0
- package/dist/plugins/deepgram/config.js.map +1 -0
- package/dist/plugins/deepgram/handler.d.ts +87 -0
- package/dist/plugins/deepgram/handler.d.ts.map +1 -0
- package/dist/plugins/deepgram/handler.js +268 -0
- package/dist/plugins/deepgram/handler.js.map +1 -0
- package/dist/plugins/deepgram/index.d.ts +11 -0
- package/dist/plugins/deepgram/index.d.ts.map +1 -0
- package/dist/plugins/deepgram/index.js +76 -0
- package/dist/plugins/deepgram/index.js.map +1 -0
- package/dist/plugins/echo/cli.d.ts +3 -0
- package/dist/plugins/echo/cli.d.ts.map +1 -0
- package/dist/plugins/echo/cli.js +10 -0
- package/dist/plugins/echo/cli.js.map +1 -0
- package/dist/plugins/echo/index.d.ts +37 -0
- package/dist/plugins/echo/index.d.ts.map +1 -0
- package/dist/plugins/echo/index.js +61 -0
- package/dist/plugins/echo/index.js.map +1 -0
- package/dist/plugins/elevenlabs/agent.d.ts +72 -0
- package/dist/plugins/elevenlabs/agent.d.ts.map +1 -0
- package/dist/plugins/elevenlabs/agent.js +305 -0
- package/dist/plugins/elevenlabs/agent.js.map +1 -0
- package/dist/plugins/elevenlabs/cli.d.ts +3 -0
- package/dist/plugins/elevenlabs/cli.d.ts.map +1 -0
- package/dist/plugins/elevenlabs/cli.js +10 -0
- package/dist/plugins/elevenlabs/cli.js.map +1 -0
- package/dist/plugins/elevenlabs/config.d.ts +27 -0
- package/dist/plugins/elevenlabs/config.d.ts.map +1 -0
- package/dist/plugins/elevenlabs/config.js +42 -0
- package/dist/plugins/elevenlabs/config.js.map +1 -0
- package/dist/plugins/elevenlabs/handler.d.ts +67 -0
- package/dist/plugins/elevenlabs/handler.d.ts.map +1 -0
- package/dist/plugins/elevenlabs/handler.js +419 -0
- package/dist/plugins/elevenlabs/handler.js.map +1 -0
- package/dist/plugins/elevenlabs/index.d.ts +11 -0
- package/dist/plugins/elevenlabs/index.d.ts.map +1 -0
- package/dist/plugins/elevenlabs/index.js +72 -0
- package/dist/plugins/elevenlabs/index.js.map +1 -0
- package/dist/plugins/livekit/cli.d.ts +3 -0
- package/dist/plugins/livekit/cli.d.ts.map +1 -0
- package/dist/plugins/livekit/cli.js +10 -0
- package/dist/plugins/livekit/cli.js.map +1 -0
- package/dist/plugins/livekit/config.d.ts +47 -0
- package/dist/plugins/livekit/config.d.ts.map +1 -0
- package/dist/plugins/livekit/config.js +46 -0
- package/dist/plugins/livekit/config.js.map +1 -0
- package/dist/plugins/livekit/handler.d.ts +59 -0
- package/dist/plugins/livekit/handler.d.ts.map +1 -0
- package/dist/plugins/livekit/handler.js +211 -0
- package/dist/plugins/livekit/handler.js.map +1 -0
- package/dist/plugins/livekit/index.d.ts +6 -0
- package/dist/plugins/livekit/index.d.ts.map +1 -0
- package/dist/plugins/livekit/index.js +68 -0
- package/dist/plugins/livekit/index.js.map +1 -0
- package/dist/plugins/livekit/room.d.ts +117 -0
- package/dist/plugins/livekit/room.d.ts.map +1 -0
- package/dist/plugins/livekit/room.js +449 -0
- package/dist/plugins/livekit/room.js.map +1 -0
- package/dist/plugins/openai/agent.d.ts +74 -0
- package/dist/plugins/openai/agent.d.ts.map +1 -0
- package/dist/plugins/openai/agent.js +264 -0
- package/dist/plugins/openai/agent.js.map +1 -0
- package/dist/plugins/openai/cli.d.ts +3 -0
- package/dist/plugins/openai/cli.d.ts.map +1 -0
- package/dist/plugins/openai/cli.js +10 -0
- package/dist/plugins/openai/cli.js.map +1 -0
- package/dist/plugins/openai/config.d.ts +29 -0
- package/dist/plugins/openai/config.d.ts.map +1 -0
- package/dist/plugins/openai/config.js +37 -0
- package/dist/plugins/openai/config.js.map +1 -0
- package/dist/plugins/openai/handler.d.ts +65 -0
- package/dist/plugins/openai/handler.d.ts.map +1 -0
- package/dist/plugins/openai/handler.js +297 -0
- package/dist/plugins/openai/handler.js.map +1 -0
- package/dist/plugins/openai/index.d.ts +6 -0
- package/dist/plugins/openai/index.d.ts.map +1 -0
- package/dist/plugins/openai/index.js +72 -0
- package/dist/plugins/openai/index.js.map +1 -0
- package/dist/plugins/openclaw/allowlist.d.ts +9 -0
- package/dist/plugins/openclaw/allowlist.d.ts.map +1 -0
- package/dist/plugins/openclaw/allowlist.js +11 -0
- package/dist/plugins/openclaw/allowlist.js.map +1 -0
- package/dist/plugins/openclaw/config.d.ts +50 -0
- package/dist/plugins/openclaw/config.d.ts.map +1 -0
- package/dist/plugins/openclaw/config.js +53 -0
- package/dist/plugins/openclaw/config.js.map +1 -0
- package/dist/plugins/openclaw/handler.d.ts +90 -0
- package/dist/plugins/openclaw/handler.d.ts.map +1 -0
- package/dist/plugins/openclaw/handler.js +146 -0
- package/dist/plugins/openclaw/handler.js.map +1 -0
- package/dist/plugins/openclaw/index.d.ts +55 -0
- package/dist/plugins/openclaw/index.d.ts.map +1 -0
- package/dist/plugins/openclaw/index.js +89 -0
- package/dist/plugins/openclaw/index.js.map +1 -0
- package/dist/plugins/openclaw/openclaw.plugin.json +74 -0
- package/dist/plugins/openclaw/package.json +14 -0
- package/dist/plugins/openclaw/realtime.d.ts +82 -0
- package/dist/plugins/openclaw/realtime.d.ts.map +1 -0
- package/dist/plugins/openclaw/realtime.js +238 -0
- package/dist/plugins/openclaw/realtime.js.map +1 -0
- package/dist/plugins/openclaw/runtime.d.ts +19 -0
- package/dist/plugins/openclaw/runtime.d.ts.map +1 -0
- package/dist/plugins/openclaw/runtime.js +160 -0
- package/dist/plugins/openclaw/runtime.js.map +1 -0
- package/dist/policy.d.ts +38 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +95 -0
- package/dist/policy.js.map +1 -0
- package/dist/protocol.d.ts +44 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +77 -0
- package/dist/protocol.js.map +1 -0
- package/dist/protocolRuntime.d.ts +19 -0
- package/dist/protocolRuntime.d.ts.map +1 -0
- package/dist/protocolRuntime.js +78 -0
- package/dist/protocolRuntime.js.map +1 -0
- package/dist/smoke.d.ts +65 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +293 -0
- package/dist/smoke.js.map +1 -0
- package/dist/startup.d.ts +74 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +112 -0
- package/dist/startup.js.map +1 -0
- package/dist/tile.d.ts +101 -0
- package/dist/tile.d.ts.map +1 -0
- package/dist/tile.js +195 -0
- package/dist/tile.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/dist/vision.d.ts +160 -0
- package/dist/vision.d.ts.map +1 -0
- package/dist/vision.js +301 -0
- package/dist/vision.js.map +1 -0
- package/dist/visionTools.d.ts +237 -0
- package/dist/visionTools.d.ts.map +1 -0
- package/dist/visionTools.js +578 -0
- package/dist/visionTools.js.map +1 -0
- package/dist/voice.d.ts +143 -0
- package/dist/voice.d.ts.map +1 -0
- package/dist/voice.js +403 -0
- package/dist/voice.js.map +1 -0
- package/package.json +129 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { logger } from "../../log.js";
|
|
4
|
+
import { StartupBuffer } from "../../startup.js";
|
|
5
|
+
import { AgentSocket, buildStart, } from "./agent.js";
|
|
6
|
+
import { cartesiaConfigFromEnv } from "./config.js";
|
|
7
|
+
const MAX_PENDING_AUDIO = 200;
|
|
8
|
+
/**
|
|
9
|
+
* The SDK renders a key press as a finished sentence, which is what a model
|
|
10
|
+
* wants. Line has a real dtmf event, so the digit is read back out of the
|
|
11
|
+
* sentence the SDK generated. Safe to do because that sentence is the SDK's own,
|
|
12
|
+
* fixed and covered by a conformance vector, rather than anything a caller can
|
|
13
|
+
* influence.
|
|
14
|
+
*/
|
|
15
|
+
const DTMF_SENTENCE = /pressed the "([^"]+)" key/;
|
|
16
|
+
/** One Microsoft Teams call answered by one Cartesia Line agent. */
|
|
17
|
+
export class CartesiaHandler {
|
|
18
|
+
#config;
|
|
19
|
+
#connect;
|
|
20
|
+
#call;
|
|
21
|
+
#agent;
|
|
22
|
+
#closed = false;
|
|
23
|
+
// Holds BOTH the caller's first words and the first context, so neither
|
|
24
|
+
// is lost while the provider is still connecting.
|
|
25
|
+
#pending = new StartupBuffer();
|
|
26
|
+
#pendingAudio = [];
|
|
27
|
+
constructor(options = {}) {
|
|
28
|
+
this.#config = options.config ?? cartesiaConfigFromEnv();
|
|
29
|
+
this.#connect = options.connect ?? AgentSocket.connect.bind(AgentSocket);
|
|
30
|
+
}
|
|
31
|
+
async onStart(session) {
|
|
32
|
+
this.#call = session;
|
|
33
|
+
const caller = session.start.caller;
|
|
34
|
+
let agent;
|
|
35
|
+
try {
|
|
36
|
+
agent = await this.#connect(this.#config, (message) => this.#onAgentMessage(message), (payload) => this.#onAgentAudio(payload), (code, reason) => this.#onAgentClose(code, reason));
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
logger.error(`standin: could not open the Cartesia stream: ${String(err)}`);
|
|
40
|
+
await session.end("agent-unavailable");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// The call can end during the connect above.
|
|
44
|
+
if (this.#closed) {
|
|
45
|
+
await agent.aclose();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.#agent = agent;
|
|
49
|
+
agent.sendStart(buildStart(agent.streamId, this.#config, {
|
|
50
|
+
callerName: caller.displayName ?? "the caller",
|
|
51
|
+
tenantId: caller.tenantId ?? "unknown-tenant",
|
|
52
|
+
direction: session.start.direction,
|
|
53
|
+
}, session.callId));
|
|
54
|
+
for (const chunk of this.#pendingAudio.splice(0))
|
|
55
|
+
agent.sendAudioChunk(chunk);
|
|
56
|
+
}
|
|
57
|
+
async onCallerAudio(pcm) {
|
|
58
|
+
const chunk = pcm.toString("base64");
|
|
59
|
+
const agent = this.#agent;
|
|
60
|
+
if (agent === undefined || !agent.isOpen) {
|
|
61
|
+
this.#pending.audio(pcm);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
agent.sendAudioChunk(chunk);
|
|
65
|
+
}
|
|
66
|
+
/** Everything the call knows, handed to the agent's own code. */
|
|
67
|
+
async onContext(text) {
|
|
68
|
+
const agent = this.#agent;
|
|
69
|
+
if (agent === undefined || !agent.isOpen) {
|
|
70
|
+
// Held rather than dropped: the "there are N people here, stay quiet"
|
|
71
|
+
// line and the recording change both land in this gap.
|
|
72
|
+
this.#pending.context(text);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const digit = DTMF_SENTENCE.exec(text);
|
|
76
|
+
if (digit?.[1]) {
|
|
77
|
+
agent.sendDtmf(digit[1]);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
agent.sendCustom({ from: "msteams", context: text });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* There is no inject-speech channel on this wire, so the line is handed to the
|
|
84
|
+
* agent's code as context and it decides how to say it.
|
|
85
|
+
*/
|
|
86
|
+
async onGoodbye(text) {
|
|
87
|
+
const agent = this.#agent;
|
|
88
|
+
if (agent !== undefined && agent.isOpen) {
|
|
89
|
+
agent.sendCustom({ from: "msteams", goodbye: text });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async aclose() {
|
|
93
|
+
this.#closed = true;
|
|
94
|
+
const agent = this.#agent;
|
|
95
|
+
this.#agent = undefined;
|
|
96
|
+
if (agent !== undefined) {
|
|
97
|
+
try {
|
|
98
|
+
await agent.aclose();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Teardown must not throw: the slot is freed either way.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// ---- what Cartesia sends us ---------------------------------------------
|
|
106
|
+
async #onAgentAudio(payloadBase64) {
|
|
107
|
+
const pcm = Buffer.from(payloadBase64, "base64");
|
|
108
|
+
// Buffer.from never throws on bad input, it silently discards what it
|
|
109
|
+
// cannot read, so re-encoding is the only way to know this really is the
|
|
110
|
+
// payload that was sent.
|
|
111
|
+
if (pcm.length === 0 || pcm.toString("base64") !== payloadBase64) {
|
|
112
|
+
logger.warn("standin: Cartesia sent unusable audio; dropping the frame");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
await this.#call?.sendAudio(pcm);
|
|
116
|
+
}
|
|
117
|
+
async #onAgentMessage(message) {
|
|
118
|
+
switch (message.event) {
|
|
119
|
+
case "clear":
|
|
120
|
+
// The agent is telling us the caller barged in. Flushing what StandIn
|
|
121
|
+
// has buffered is what actually stops the bot mid-word.
|
|
122
|
+
await this.#call?.cancelPlayback();
|
|
123
|
+
break;
|
|
124
|
+
case "end":
|
|
125
|
+
if (!this.#closed)
|
|
126
|
+
await this.#call?.end("agent-ended-call");
|
|
127
|
+
break;
|
|
128
|
+
case "transfer_call":
|
|
129
|
+
// A phone-network transfer has no meaning on a Microsoft Teams call.
|
|
130
|
+
logger.info("standin: Cartesia asked for a call transfer, which this lane cannot do");
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async #onAgentClose(code, reason) {
|
|
137
|
+
logger.info(`standin: the Cartesia stream closed (${code} ${reason})`);
|
|
138
|
+
if (!this.#closed)
|
|
139
|
+
await this.#call?.end("agent-disconnected");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/plugins/cartesia/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AgentSocket, WIRE_SAMPLE_RATE_HZ, buildStart, mintAccessToken, type AgentMessage, type AgentPort, type CallerContext, } from "./agent.js";
|
|
2
|
+
export { cartesiaConfigFromEnv, type CartesiaConfig } from "./config.js";
|
|
3
|
+
export { CartesiaHandler, type CartesiaHandlerOptions, type Connect, } from "./handler.js";
|
|
4
|
+
/** Answer Microsoft Teams calls with Cartesia until the process is interrupted. */
|
|
5
|
+
export declare function serve(): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/cartesia/index.ts"],"names":[],"mappings":"AAqCA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,OAAO,GACb,MAAM,cAAc,CAAC;AAEtB,mFAAmF;AACnF,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB3C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* Answer Microsoft Teams calls with a Cartesia Line agent.
|
|
5
|
+
*
|
|
6
|
+
* StandIn answers the Microsoft Teams call and dials this worker. This
|
|
7
|
+
* plugin answers that dial, opens one Line agent stream per call, and
|
|
8
|
+
* relays the audio both ways.
|
|
9
|
+
*
|
|
10
|
+
* Nothing to install beyond the SDK: Cartesia is reached over an ordinary
|
|
11
|
+
* WebSocket, so this plugin adds no dependency.
|
|
12
|
+
*
|
|
13
|
+
* ```bash
|
|
14
|
+
* npm install @komaa/standin-sdk
|
|
15
|
+
*
|
|
16
|
+
* export STANDIN_SECRET=... # your StandIn connection secret
|
|
17
|
+
* export CARTESIA_API_KEY=...
|
|
18
|
+
* export CARTESIA_AGENT_ID=...
|
|
19
|
+
* npx standin-cartesia
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The agent itself is your code on Cartesia's platform, so this plugin is
|
|
23
|
+
* transport and nothing else: there are no call capabilities to declare and no
|
|
24
|
+
* tools to answer here. Caller details reach your agent as stream metadata, and
|
|
25
|
+
* call context arrives as `custom` events for your agent code to act on.
|
|
26
|
+
*
|
|
27
|
+
* Audio is pinned to `pcm_16000` in both directions, which is exactly what
|
|
28
|
+
* StandIn speaks, so nothing resamples anything.
|
|
29
|
+
*
|
|
30
|
+
* The Python twin is `standin.plugins.cartesia`.
|
|
31
|
+
*/
|
|
32
|
+
import { CallServer } from "../../index.js";
|
|
33
|
+
import { CartesiaHandler } from "./handler.js";
|
|
34
|
+
import { cartesiaConfigFromEnv } from "./config.js";
|
|
35
|
+
export { AgentSocket, WIRE_SAMPLE_RATE_HZ, buildStart, mintAccessToken, } from "./agent.js";
|
|
36
|
+
export { cartesiaConfigFromEnv } from "./config.js";
|
|
37
|
+
export { CartesiaHandler, } from "./handler.js";
|
|
38
|
+
/** Answer Microsoft Teams calls with Cartesia until the process is interrupted. */
|
|
39
|
+
export async function serve() {
|
|
40
|
+
const config = cartesiaConfigFromEnv();
|
|
41
|
+
const server = new CallServer({
|
|
42
|
+
handlerFactory: () => new CartesiaHandler({ config }),
|
|
43
|
+
});
|
|
44
|
+
await server.start();
|
|
45
|
+
await new Promise((resolve) => {
|
|
46
|
+
const stop = () => {
|
|
47
|
+
resolve();
|
|
48
|
+
};
|
|
49
|
+
process.once("SIGINT", stop);
|
|
50
|
+
process.once("SIGTERM", stop);
|
|
51
|
+
});
|
|
52
|
+
await server.aclose();
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/cartesia/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,eAAe,GAIhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAuB,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,eAAe,GAGhB,MAAM,cAAc,CAAC;AAEtB,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KACtD,CAAC,CAAC;IACH,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,60 @@
|
|
|
1
|
+
import type { DeepgramConfig } from "./config.js";
|
|
2
|
+
/** The one wire rate: StandIn's PCM16 at 16 kHz is Deepgram's linear16 at 16000. */
|
|
3
|
+
export declare const WIRE_SAMPLE_RATE_HZ = 16000;
|
|
4
|
+
/** A JSON frame from Deepgram. Only `type` is guaranteed. */
|
|
5
|
+
export type AgentMessage = Record<string, unknown> & {
|
|
6
|
+
type: string;
|
|
7
|
+
};
|
|
8
|
+
/** Caller details folded into the prompt. */
|
|
9
|
+
export interface CallerContext {
|
|
10
|
+
callerName: string;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
direction: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Assemble the agent prompt: your instructions, who is calling, and what has
|
|
16
|
+
* happened on the call so far.
|
|
17
|
+
*
|
|
18
|
+
* The live notes are here rather than in their own message because the Voice
|
|
19
|
+
* Agent API has no non-interrupting context channel. Context rides an updated
|
|
20
|
+
* prompt instead, which is why the handler keeps that list bounded.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildPrompt(config: DeepgramConfig, caller: CallerContext, notes?: readonly string[]): string;
|
|
23
|
+
/** The Settings message, sent once per call right after Welcome. */
|
|
24
|
+
export declare function buildSettings(config: DeepgramConfig, prompt: string, functions: Array<Record<string, unknown>>): Record<string, unknown>;
|
|
25
|
+
/** What the relay needs from an agent connection. Tests substitute their own. */
|
|
26
|
+
export interface AgentPort {
|
|
27
|
+
readonly isOpen: boolean;
|
|
28
|
+
sendSettings(settings: Record<string, unknown>): void;
|
|
29
|
+
sendAudio(pcm: Buffer): void;
|
|
30
|
+
updatePrompt(prompt: string): void;
|
|
31
|
+
injectAgentMessage(text: string): void;
|
|
32
|
+
sendFunctionResult(callId: string, name: string, content: string): void;
|
|
33
|
+
aclose(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/** The socket to one Deepgram Voice Agent conversation. */
|
|
36
|
+
export declare class AgentSocket implements AgentPort {
|
|
37
|
+
#private;
|
|
38
|
+
private readonly config;
|
|
39
|
+
private constructor();
|
|
40
|
+
/** Open the socket and wait for Welcome. Retries once on a transient failure. */
|
|
41
|
+
static connect(config: DeepgramConfig, onMessage: (message: AgentMessage) => void | Promise<void>, onAudio: (pcm: Buffer) => void | Promise<void>, onClose: (code: number, reason: string) => void | Promise<void>): Promise<AgentSocket>;
|
|
42
|
+
get isOpen(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The caller's voice, as a raw binary frame.
|
|
45
|
+
*
|
|
46
|
+
* Dropped rather than queued past the buffer ceiling: on a stalled socket the
|
|
47
|
+
* alternative is an unbounded pile of stale audio, and stale caller audio is
|
|
48
|
+
* worth nothing by the time it arrives.
|
|
49
|
+
*/
|
|
50
|
+
sendAudio(pcm: Buffer): void;
|
|
51
|
+
sendSettings(settings: Record<string, unknown>): void;
|
|
52
|
+
/** Replace the agent's prompt mid-call, which is how context arrives. */
|
|
53
|
+
updatePrompt(prompt: string): void;
|
|
54
|
+
/** Make the agent say this, now, interrupting whatever it was saying. */
|
|
55
|
+
injectAgentMessage(text: string): void;
|
|
56
|
+
sendFunctionResult(callId: string, name: string, content: string): void;
|
|
57
|
+
/** Close the conversation. Safe to call twice. */
|
|
58
|
+
aclose(): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/plugins/deepgram/agent.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAe1C,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,aAAa,EACrB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,MAAM,CAeR;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+CzB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtD,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,2DAA2D;AAC3D,qBAAa,WAAY,YAAW,SAAS;;IAQvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAA3C,OAAO;IAEP,iFAAiF;WACpE,OAAO,CAClB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC1D,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC9C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC9D,OAAO,CAAC,WAAW,CAAC;IAoJvB,IAAI,MAAM,IAAI,OAAO,CAEpB;IAYD;;;;;;OAMG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqB5B,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIrD,yEAAyE;IACzE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIlC,yEAAyE;IACzE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAItC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIvE,kDAAkD;IAC5C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ9B"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* One Deepgram Voice Agent conversation, as a socket.
|
|
5
|
+
*
|
|
6
|
+
* Thin on purpose: framing and send helpers only. What any of it means to a
|
|
7
|
+
* Microsoft Teams call is in `handler.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Two things about this wire are worth knowing before reading the code. Audio
|
|
10
|
+
* travels as raw BINARY frames in both directions, not base64 inside JSON, so
|
|
11
|
+
* the hot path here is a copy rather than an encode. And the session is pinned
|
|
12
|
+
* to `linear16` at 16 kHz both ways, which is exactly what StandIn speaks, so
|
|
13
|
+
* nothing in this plugin resamples anything.
|
|
14
|
+
*
|
|
15
|
+
* The Python twin is `standin.plugins.deepgram.agent`.
|
|
16
|
+
*/
|
|
17
|
+
import { WebSocket } from "ws";
|
|
18
|
+
import { logger } from "../../log.js";
|
|
19
|
+
/** The one wire rate: StandIn's PCM16 at 16 kHz is Deepgram's linear16 at 16000. */
|
|
20
|
+
export const WIRE_SAMPLE_RATE_HZ = 16_000;
|
|
21
|
+
/**
|
|
22
|
+
* The socket idles out when no audio is flowing, which happens whenever the
|
|
23
|
+
* caller is simply listening. Cheap to send, and sent for the whole call.
|
|
24
|
+
*/
|
|
25
|
+
const KEEPALIVE_INTERVAL_MS = 8_000;
|
|
26
|
+
const CONNECT_TIMEOUT_MS = 10_000;
|
|
27
|
+
/** How long to wait for the server's Welcome. Settings may not be sent before it. */
|
|
28
|
+
const WELCOME_TIMEOUT_MS = 10_000;
|
|
29
|
+
const MAX_SEND_BUFFER_BYTES = 1024 * 1024;
|
|
30
|
+
/**
|
|
31
|
+
* Assemble the agent prompt: your instructions, who is calling, and what has
|
|
32
|
+
* happened on the call so far.
|
|
33
|
+
*
|
|
34
|
+
* The live notes are here rather than in their own message because the Voice
|
|
35
|
+
* Agent API has no non-interrupting context channel. Context rides an updated
|
|
36
|
+
* prompt instead, which is why the handler keeps that list bounded.
|
|
37
|
+
*/
|
|
38
|
+
export function buildPrompt(config, caller, notes = []) {
|
|
39
|
+
const lines = [
|
|
40
|
+
config.instructions,
|
|
41
|
+
"",
|
|
42
|
+
`Call context: you are speaking with ${caller.callerName} ` +
|
|
43
|
+
`(tenant: ${caller.tenantId}) on an ${caller.direction} call.`,
|
|
44
|
+
];
|
|
45
|
+
if (notes.length > 0) {
|
|
46
|
+
lines.push("", "Live call context (most recent last):", ...notes.map((n) => `- ${n}`));
|
|
47
|
+
}
|
|
48
|
+
return lines.join("\n");
|
|
49
|
+
}
|
|
50
|
+
/** The Settings message, sent once per call right after Welcome. */
|
|
51
|
+
export function buildSettings(config, prompt, functions) {
|
|
52
|
+
const think = {
|
|
53
|
+
provider: { type: config.thinkProvider, model: config.thinkModel },
|
|
54
|
+
prompt,
|
|
55
|
+
functions,
|
|
56
|
+
};
|
|
57
|
+
if (config.thinkEndpointUrl) {
|
|
58
|
+
const endpoint = { url: config.thinkEndpointUrl };
|
|
59
|
+
if (Object.keys(config.thinkEndpointHeaders).length > 0) {
|
|
60
|
+
endpoint.headers = config.thinkEndpointHeaders;
|
|
61
|
+
}
|
|
62
|
+
think.endpoint = endpoint;
|
|
63
|
+
}
|
|
64
|
+
const agent = {
|
|
65
|
+
listen: {
|
|
66
|
+
provider: {
|
|
67
|
+
type: "deepgram",
|
|
68
|
+
model: config.listenModel,
|
|
69
|
+
language: config.language,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
think,
|
|
73
|
+
speak: {
|
|
74
|
+
provider: {
|
|
75
|
+
type: "deepgram",
|
|
76
|
+
model: config.speakModel,
|
|
77
|
+
language: config.language,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
if (config.greeting)
|
|
82
|
+
agent.greeting = config.greeting;
|
|
83
|
+
return {
|
|
84
|
+
type: "Settings",
|
|
85
|
+
audio: {
|
|
86
|
+
// "container" is an output-side field: every official Settings example
|
|
87
|
+
// omits it on input, and sending it there is rejected.
|
|
88
|
+
input: { encoding: "linear16", sample_rate: WIRE_SAMPLE_RATE_HZ },
|
|
89
|
+
output: {
|
|
90
|
+
encoding: "linear16",
|
|
91
|
+
sample_rate: WIRE_SAMPLE_RATE_HZ,
|
|
92
|
+
container: "none",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
agent,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** The socket to one Deepgram Voice Agent conversation. */
|
|
99
|
+
export class AgentSocket {
|
|
100
|
+
config;
|
|
101
|
+
#ws;
|
|
102
|
+
#keepalive;
|
|
103
|
+
#pendingBytes = 0;
|
|
104
|
+
#dropped = 0;
|
|
105
|
+
#lastDropWarning = 0;
|
|
106
|
+
#closedByUs = false;
|
|
107
|
+
constructor(config) {
|
|
108
|
+
this.config = config;
|
|
109
|
+
}
|
|
110
|
+
/** Open the socket and wait for Welcome. Retries once on a transient failure. */
|
|
111
|
+
static async connect(config, onMessage, onAudio, onClose) {
|
|
112
|
+
const socket = new AgentSocket(config);
|
|
113
|
+
try {
|
|
114
|
+
await socket.#open();
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
logger.warn(`standin: Deepgram connect failed (${String(err)}); retrying once`);
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
119
|
+
await socket.#open();
|
|
120
|
+
}
|
|
121
|
+
socket.#listen(onMessage, onAudio, onClose);
|
|
122
|
+
socket.#keepalive = setInterval(() => {
|
|
123
|
+
socket.#send({ type: "KeepAlive" });
|
|
124
|
+
}, KEEPALIVE_INTERVAL_MS);
|
|
125
|
+
socket.#keepalive.unref?.();
|
|
126
|
+
return socket;
|
|
127
|
+
}
|
|
128
|
+
async #open() {
|
|
129
|
+
const ws = new WebSocket(`wss://${this.config.agentHost}/v1/agent/converse`, {
|
|
130
|
+
headers: { authorization: `Token ${this.config.apiKey}` },
|
|
131
|
+
maxPayload: 16 * 1024 * 1024,
|
|
132
|
+
});
|
|
133
|
+
await new Promise((resolve, reject) => {
|
|
134
|
+
const fail = setTimeout(() => {
|
|
135
|
+
ws.terminate();
|
|
136
|
+
reject(new Error("the Deepgram socket did not open in time"));
|
|
137
|
+
}, CONNECT_TIMEOUT_MS);
|
|
138
|
+
fail.unref?.();
|
|
139
|
+
ws.once("open", () => {
|
|
140
|
+
clearTimeout(fail);
|
|
141
|
+
resolve();
|
|
142
|
+
});
|
|
143
|
+
ws.once("error", (err) => {
|
|
144
|
+
clearTimeout(fail);
|
|
145
|
+
reject(err);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
await this.#awaitWelcome(ws);
|
|
149
|
+
this.#ws = ws;
|
|
150
|
+
}
|
|
151
|
+
async #awaitWelcome(ws) {
|
|
152
|
+
await new Promise((resolve, reject) => {
|
|
153
|
+
const timer = setTimeout(() => {
|
|
154
|
+
cleanup();
|
|
155
|
+
ws.terminate();
|
|
156
|
+
reject(new Error("no Welcome from Deepgram within the timeout"));
|
|
157
|
+
}, WELCOME_TIMEOUT_MS);
|
|
158
|
+
timer.unref?.();
|
|
159
|
+
const onMessage = (raw, isBinary) => {
|
|
160
|
+
if (isBinary)
|
|
161
|
+
return; // audio cannot arrive before Settings; ignore it
|
|
162
|
+
let message;
|
|
163
|
+
try {
|
|
164
|
+
message = JSON.parse(raw.toString());
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (typeof message !== "object" || message === null)
|
|
170
|
+
return;
|
|
171
|
+
const typed = message;
|
|
172
|
+
if (typed.type === "Welcome") {
|
|
173
|
+
cleanup();
|
|
174
|
+
resolve();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (typed.type === "Error") {
|
|
178
|
+
// A bad key or a bad config must fail HERE with the real reason,
|
|
179
|
+
// rather than being swallowed until the Welcome timeout reports
|
|
180
|
+
// something generic ten seconds later.
|
|
181
|
+
cleanup();
|
|
182
|
+
ws.terminate();
|
|
183
|
+
reject(new Error(`Deepgram rejected the session: ${String(typed.code ?? "unknown")}: ` +
|
|
184
|
+
String(typed.description ?? "no description")));
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const onClose = () => {
|
|
188
|
+
cleanup();
|
|
189
|
+
reject(new Error("the socket closed before Welcome"));
|
|
190
|
+
};
|
|
191
|
+
const cleanup = () => {
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
ws.off("message", onMessage);
|
|
194
|
+
ws.off("close", onClose);
|
|
195
|
+
};
|
|
196
|
+
ws.on("message", onMessage);
|
|
197
|
+
ws.once("close", onClose);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
#listen(onMessage, onAudio, onClose) {
|
|
201
|
+
const ws = this.#ws;
|
|
202
|
+
if (ws === undefined)
|
|
203
|
+
return;
|
|
204
|
+
ws.on("message", (raw, isBinary) => {
|
|
205
|
+
if (isBinary) {
|
|
206
|
+
void Promise.resolve(onAudio(Buffer.from(raw))).catch((err) => {
|
|
207
|
+
logger.error(`standin: handling Deepgram audio failed: ${String(err)}`);
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
let message;
|
|
212
|
+
try {
|
|
213
|
+
message = JSON.parse(raw.toString());
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
logger.warn("standin: Deepgram sent an unparseable frame; dropping");
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (typeof message !== "object" || message === null)
|
|
220
|
+
return;
|
|
221
|
+
const typed = message;
|
|
222
|
+
if (typeof typed.type !== "string")
|
|
223
|
+
return;
|
|
224
|
+
void Promise.resolve(onMessage(typed)).catch((err) => {
|
|
225
|
+
logger.error(`standin: handling Deepgram ${typed.type} failed: ${String(err)}`);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
ws.on("close", (code, reason) => {
|
|
229
|
+
if (this.#keepalive)
|
|
230
|
+
clearInterval(this.#keepalive);
|
|
231
|
+
void onClose(code, reason.toString());
|
|
232
|
+
});
|
|
233
|
+
ws.on("error", (err) => {
|
|
234
|
+
logger.warn(`standin: the Deepgram socket failed: ${String(err)}`);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
get isOpen() {
|
|
238
|
+
return this.#ws !== undefined && this.#ws.readyState === WebSocket.OPEN;
|
|
239
|
+
}
|
|
240
|
+
#send(message) {
|
|
241
|
+
const ws = this.#ws;
|
|
242
|
+
if (ws === undefined || ws.readyState !== WebSocket.OPEN)
|
|
243
|
+
return;
|
|
244
|
+
const payload = JSON.stringify(message);
|
|
245
|
+
this.#pendingBytes += payload.length;
|
|
246
|
+
ws.send(payload, () => {
|
|
247
|
+
this.#pendingBytes -= payload.length;
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The caller's voice, as a raw binary frame.
|
|
252
|
+
*
|
|
253
|
+
* Dropped rather than queued past the buffer ceiling: on a stalled socket the
|
|
254
|
+
* alternative is an unbounded pile of stale audio, and stale caller audio is
|
|
255
|
+
* worth nothing by the time it arrives.
|
|
256
|
+
*/
|
|
257
|
+
sendAudio(pcm) {
|
|
258
|
+
const ws = this.#ws;
|
|
259
|
+
if (ws === undefined || ws.readyState !== WebSocket.OPEN)
|
|
260
|
+
return;
|
|
261
|
+
if (this.#pendingBytes > MAX_SEND_BUFFER_BYTES) {
|
|
262
|
+
this.#dropped += 1;
|
|
263
|
+
const now = Date.now();
|
|
264
|
+
if (now - this.#lastDropWarning >= 1000) {
|
|
265
|
+
logger.warn(`standin: Deepgram send backpressure, dropped ${this.#dropped} frame(s)`);
|
|
266
|
+
this.#lastDropWarning = now;
|
|
267
|
+
this.#dropped = 0;
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
this.#pendingBytes += pcm.length;
|
|
272
|
+
ws.send(pcm, { binary: true }, () => {
|
|
273
|
+
this.#pendingBytes -= pcm.length;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
sendSettings(settings) {
|
|
277
|
+
this.#send(settings);
|
|
278
|
+
}
|
|
279
|
+
/** Replace the agent's prompt mid-call, which is how context arrives. */
|
|
280
|
+
updatePrompt(prompt) {
|
|
281
|
+
this.#send({ type: "UpdatePrompt", prompt });
|
|
282
|
+
}
|
|
283
|
+
/** Make the agent say this, now, interrupting whatever it was saying. */
|
|
284
|
+
injectAgentMessage(text) {
|
|
285
|
+
this.#send({ type: "InjectAgentMessage", content: text });
|
|
286
|
+
}
|
|
287
|
+
sendFunctionResult(callId, name, content) {
|
|
288
|
+
this.#send({ type: "FunctionCallResponse", id: callId, name, content });
|
|
289
|
+
}
|
|
290
|
+
/** Close the conversation. Safe to call twice. */
|
|
291
|
+
async aclose() {
|
|
292
|
+
if (this.#closedByUs)
|
|
293
|
+
return;
|
|
294
|
+
this.#closedByUs = true;
|
|
295
|
+
if (this.#keepalive)
|
|
296
|
+
clearInterval(this.#keepalive);
|
|
297
|
+
const ws = this.#ws;
|
|
298
|
+
if (ws !== undefined && ws.readyState === WebSocket.OPEN)
|
|
299
|
+
ws.close(1000, "session-end");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/plugins/deepgram/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/plugins/deepgram/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-deepgram` */
|
|
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/deepgram/cli.ts"],"names":[],"mappings":";AACA,oCAAoC;AACpC,+BAA+B;AAE/B,6BAA6B;AAE7B,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"}
|