@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,39 @@
|
|
|
1
|
+
export declare const DEFAULT_INSTRUCTIONS: string;
|
|
2
|
+
/** Everything the Deepgram plugin needs, resolved once per worker. */
|
|
3
|
+
export interface DeepgramConfig {
|
|
4
|
+
/** `DEEPGRAM_API_KEY`. Never logged, never sent to StandIn. */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** `DEEPGRAM_AGENT_HOST`, the Voice Agent socket host. */
|
|
7
|
+
agentHost: string;
|
|
8
|
+
/** `DEEPGRAM_API_HOST`, for the REST calls. */
|
|
9
|
+
apiHost: string;
|
|
10
|
+
/** `DEEPGRAM_LISTEN_MODEL`: speech to text. */
|
|
11
|
+
listenModel: string;
|
|
12
|
+
/** `DEEPGRAM_SPEAK_MODEL`: text to speech. */
|
|
13
|
+
speakModel: string;
|
|
14
|
+
/** `DEEPGRAM_THINK_PROVIDER`: which LLM vendor Deepgram should reason with. */
|
|
15
|
+
thinkProvider: string;
|
|
16
|
+
/** `DEEPGRAM_THINK_MODEL`. */
|
|
17
|
+
thinkModel: string;
|
|
18
|
+
/** `DEEPGRAM_THINK_ENDPOINT_URL`, to point the thinking step at your own model. */
|
|
19
|
+
thinkEndpointUrl?: string;
|
|
20
|
+
/**
|
|
21
|
+
* `DEEPGRAM_THINK_ENDPOINT_HEADERS`, a JSON object. This carries YOUR model
|
|
22
|
+
* credentials, so it is never logged.
|
|
23
|
+
*/
|
|
24
|
+
thinkEndpointHeaders: Record<string, string>;
|
|
25
|
+
/** `DEEPGRAM_LANGUAGE`. */
|
|
26
|
+
language: string;
|
|
27
|
+
/** `DEEPGRAM_INSTRUCTIONS`: the agent's base prompt. */
|
|
28
|
+
instructions: string;
|
|
29
|
+
/** `DEEPGRAM_GREETING`: what the agent says first, if anything. */
|
|
30
|
+
greeting?: string;
|
|
31
|
+
/**
|
|
32
|
+
* `DEEPGRAM_LOG_TRANSCRIPTS`. Off by default, and gated a second time on the
|
|
33
|
+
* call actually being recorded.
|
|
34
|
+
*/
|
|
35
|
+
logTranscripts: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Read the configuration, or throw naming the variable that is missing. */
|
|
38
|
+
export declare function deepgramConfigFromEnv(): DeepgramConfig;
|
|
39
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/plugins/deepgram/config.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB,QAGd,CAAC;AAEpB,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAiBD,4EAA4E;AAC5E,wBAAgB,qBAAqB,IAAI,cAAc,CAgDtD"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* What the Deepgram plugin reads from the environment.
|
|
5
|
+
*
|
|
6
|
+
* One prefix, `DEEPGRAM_`, plus the SDK-wide `STANDIN_VISION_*` that every
|
|
7
|
+
* plugin shares for looking at a screen share.
|
|
8
|
+
*/
|
|
9
|
+
import { StandInError } from "../../errors.js";
|
|
10
|
+
/** Refuse a host that is not Deepgram: the API key travels to it. */
|
|
11
|
+
const ALLOWED_HOST_SUFFIX = ".deepgram.com";
|
|
12
|
+
export const DEFAULT_INSTRUCTIONS = "You are a helpful voice assistant on a live Microsoft Teams call. You are speaking " +
|
|
13
|
+
"aloud: keep replies short, natural and conversational, and never use markdown, " +
|
|
14
|
+
"lists or emoji.";
|
|
15
|
+
function required(name) {
|
|
16
|
+
const value = (process.env[name] ?? "").trim();
|
|
17
|
+
if (!value)
|
|
18
|
+
throw new StandInError(`${name} is required to answer calls with Deepgram`);
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function host(name, fallback) {
|
|
22
|
+
const value = (process.env[name] ?? "").trim() || fallback;
|
|
23
|
+
if (value !== "deepgram.com" && !value.endsWith(ALLOWED_HOST_SUFFIX)) {
|
|
24
|
+
throw new StandInError(`${name} must be a deepgram.com host, got ${value}`);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
/** Read the configuration, or throw naming the variable that is missing. */
|
|
29
|
+
export function deepgramConfigFromEnv() {
|
|
30
|
+
const rawHeaders = (process.env.DEEPGRAM_THINK_ENDPOINT_HEADERS ?? "").trim();
|
|
31
|
+
let thinkEndpointHeaders = {};
|
|
32
|
+
if (rawHeaders) {
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
parsed = JSON.parse(rawHeaders);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
throw new StandInError("DEEPGRAM_THINK_ENDPOINT_HEADERS must be a JSON object");
|
|
39
|
+
}
|
|
40
|
+
if (typeof parsed !== "object" ||
|
|
41
|
+
parsed === null ||
|
|
42
|
+
Array.isArray(parsed)) {
|
|
43
|
+
throw new StandInError("DEEPGRAM_THINK_ENDPOINT_HEADERS must be a JSON object");
|
|
44
|
+
}
|
|
45
|
+
thinkEndpointHeaders = Object.fromEntries(Object.entries(parsed).map(([k, v]) => [
|
|
46
|
+
k,
|
|
47
|
+
String(v),
|
|
48
|
+
]));
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
apiKey: required("DEEPGRAM_API_KEY"),
|
|
52
|
+
agentHost: host("DEEPGRAM_AGENT_HOST", "agent.deepgram.com"),
|
|
53
|
+
apiHost: host("DEEPGRAM_API_HOST", "api.deepgram.com"),
|
|
54
|
+
listenModel: (process.env.DEEPGRAM_LISTEN_MODEL ?? "").trim() || "nova-3",
|
|
55
|
+
speakModel: (process.env.DEEPGRAM_SPEAK_MODEL ?? "").trim() || "aura-2-thalia-en",
|
|
56
|
+
thinkProvider: (process.env.DEEPGRAM_THINK_PROVIDER ?? "").trim() || "open_ai",
|
|
57
|
+
thinkModel: (process.env.DEEPGRAM_THINK_MODEL ?? "").trim() || "gpt-4o-mini",
|
|
58
|
+
thinkEndpointUrl: (process.env.DEEPGRAM_THINK_ENDPOINT_URL ?? "").trim() || undefined,
|
|
59
|
+
thinkEndpointHeaders,
|
|
60
|
+
language: (process.env.DEEPGRAM_LANGUAGE ?? "").trim() || "en",
|
|
61
|
+
instructions: (process.env.DEEPGRAM_INSTRUCTIONS ?? "").trim() || DEFAULT_INSTRUCTIONS,
|
|
62
|
+
greeting: (process.env.DEEPGRAM_GREETING ?? "").trim() || undefined,
|
|
63
|
+
logTranscripts: process.env.DEEPGRAM_LOG_TRANSCRIPTS === "true",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/plugins/deepgram/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The relay: one Microsoft Teams call on one side, one Deepgram Voice Agent on
|
|
3
|
+
* the other.
|
|
4
|
+
*
|
|
5
|
+
* Two shapes differ from the other providers and are worth knowing:
|
|
6
|
+
*
|
|
7
|
+
* **Context rides the prompt.** The Voice Agent API has no non-interrupting
|
|
8
|
+
* context message, so participant counts and key presses are appended to a
|
|
9
|
+
* bounded rolling section of the prompt and pushed with `UpdatePrompt`. Bounded
|
|
10
|
+
* matters: the prompt is resent in full each time.
|
|
11
|
+
*
|
|
12
|
+
* **Functions are declared, not configured.** The call capabilities come from
|
|
13
|
+
* `standin/callTools`, are sent in the Settings message, and so there is
|
|
14
|
+
* nothing to set up on the Deepgram side and nothing restated here: a
|
|
15
|
+
* capability added to the SDK reaches this plugin without an edit. Add your own
|
|
16
|
+
* with {@link CustomTool} and they are declared the same way.
|
|
17
|
+
*
|
|
18
|
+
* The Python twin is `standin.plugins.deepgram.handler`.
|
|
19
|
+
*/
|
|
20
|
+
import type { CallHandler, CallSession } from "../../handler.js";
|
|
21
|
+
import { FrameDescriber, type VideoFrame } from "../../vision.js";
|
|
22
|
+
import { type AgentMessage, type AgentPort } from "./agent.js";
|
|
23
|
+
import { type DeepgramConfig } from "./config.js";
|
|
24
|
+
/** What a custom tool is told about the call it is running inside. */
|
|
25
|
+
export interface ToolContext {
|
|
26
|
+
/** The live call, so a tool can speak, show something, or hang up. */
|
|
27
|
+
call: CallSession;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the Microsoft Teams call is being recorded. Gate anything that
|
|
30
|
+
* stores what the caller said or showed on this.
|
|
31
|
+
*/
|
|
32
|
+
recording: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** A function of your own, which the agent calls and your code answers. */
|
|
35
|
+
export interface CustomTool {
|
|
36
|
+
/** Must not collide with the four built in above. */
|
|
37
|
+
name: string;
|
|
38
|
+
/**
|
|
39
|
+
* What the model reads to decide whether to call it. This is the prompt for
|
|
40
|
+
* the tool, so write it for a model, not for a developer.
|
|
41
|
+
*/
|
|
42
|
+
description: string;
|
|
43
|
+
/** JSON schema for the parameters. */
|
|
44
|
+
parameters?: Record<string, unknown>;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the string the agent is told, which it will read out or reason
|
|
47
|
+
* from. Keep it fast: the caller is waiting in silence while it runs.
|
|
48
|
+
*/
|
|
49
|
+
handler: (params: Record<string, unknown>, ctx: ToolContext) => string | Promise<string>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The call capabilities every Deepgram session gets, declared in Settings.
|
|
53
|
+
* These have no endpoint, which is what tells Deepgram to ask the client to run
|
|
54
|
+
* them. The list is the SDK's, in Deepgram's shape, so every provider offers
|
|
55
|
+
* the same agent and a new capability needs no edit here.
|
|
56
|
+
*/
|
|
57
|
+
export declare const BUILT_IN_TOOLS: Array<Record<string, unknown>>;
|
|
58
|
+
/** How the handler reaches Deepgram. Replaceable so tests need no network. */
|
|
59
|
+
export type Connect = (config: DeepgramConfig, onMessage: (message: AgentMessage) => void | Promise<void>, onAudio: (pcm: Buffer) => void | Promise<void>, onClose: (code: number, reason: string) => void | Promise<void>) => Promise<AgentPort>;
|
|
60
|
+
/** Options for {@link DeepgramHandler}. */
|
|
61
|
+
export interface DeepgramHandlerOptions {
|
|
62
|
+
config?: DeepgramConfig;
|
|
63
|
+
tools?: CustomTool[];
|
|
64
|
+
describer?: FrameDescriber;
|
|
65
|
+
connect?: Connect;
|
|
66
|
+
}
|
|
67
|
+
/** One Microsoft Teams call answered by one Deepgram Voice Agent. */
|
|
68
|
+
export declare class DeepgramHandler implements CallHandler {
|
|
69
|
+
#private;
|
|
70
|
+
constructor(options?: DeepgramHandlerOptions);
|
|
71
|
+
onStart(session: CallSession): Promise<void>;
|
|
72
|
+
/** The caller's voice, straight through as a binary frame. */
|
|
73
|
+
onCallerAudio(pcm: Buffer): Promise<void>;
|
|
74
|
+
/** Fold context into the prompt, because this API has nowhere else to put it. */
|
|
75
|
+
/**
|
|
76
|
+
* Keep a short history, so a question about a slide already gone can still be
|
|
77
|
+
* answered. Only kept while the call is recorded.
|
|
78
|
+
*/
|
|
79
|
+
onVideoFrame(frame: VideoFrame): Promise<void>;
|
|
80
|
+
onContext(text: string): Promise<void>;
|
|
81
|
+
/** Say this line now, interrupting whatever the agent was saying. */
|
|
82
|
+
onGoodbye(text: string): Promise<void>;
|
|
83
|
+
aclose(): Promise<void>;
|
|
84
|
+
/** Run one function and return what the agent is told. Exposed for tests. */
|
|
85
|
+
dispatch(name: string, params: Record<string, unknown>): Promise<string>;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/plugins/deepgram/handler.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKjE,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EAEf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAczE,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,IAAI,EAAE,WAAW,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;OAGG;IACH,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,EAAE,WAAW,KACb,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACrC,CAAC;AAMtB,8EAA8E;AAC9E,MAAM,MAAM,OAAO,GAAG,CACpB,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,KAC5D,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qEAAqE;AACrE,qBAAa,eAAgB,YAAW,WAAW;;gBAoBrC,OAAO,GAAE,sBAA2B;IAgC1C,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAgElD,8DAA8D;IACxD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,iFAAiF;IACjF;;;OAGG;IACG,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5C,qEAAqE;IAC/D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAuG7B,6EAA6E;IACvE,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC;CAyBnB"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { CallTools, toolSchemas } from "../../callTools.js";
|
|
4
|
+
import { fetchPublicImage } from "../../fetch.js";
|
|
5
|
+
import { logger } from "../../log.js";
|
|
6
|
+
import { StartupBuffer } from "../../startup.js";
|
|
7
|
+
import { FrameDescriber } from "../../vision.js";
|
|
8
|
+
import { VisionTools } from "../../visionTools.js";
|
|
9
|
+
import { AgentSocket, buildPrompt, buildSettings, } from "./agent.js";
|
|
10
|
+
import { deepgramConfigFromEnv } from "./config.js";
|
|
11
|
+
const MAX_EMOTION_CHARS = 40;
|
|
12
|
+
const MAX_CAPTION_CHARS = 200;
|
|
13
|
+
const IMAGE_FETCH_TIMEOUT_MS = 10_000;
|
|
14
|
+
/**
|
|
15
|
+
* How many context notes ride in the prompt. The whole prompt is resent on every
|
|
16
|
+
* update, so this is a cost per participant change, not a one-off.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_CONTEXT_NOTES = 8;
|
|
19
|
+
const MAX_PENDING_AUDIO = 200;
|
|
20
|
+
/**
|
|
21
|
+
* The call capabilities every Deepgram session gets, declared in Settings.
|
|
22
|
+
* These have no endpoint, which is what tells Deepgram to ask the client to run
|
|
23
|
+
* them. The list is the SDK's, in Deepgram's shape, so every provider offers
|
|
24
|
+
* the same agent and a new capability needs no edit here.
|
|
25
|
+
*/
|
|
26
|
+
export const BUILT_IN_TOOLS = toolSchemas("flat");
|
|
27
|
+
const BUILT_IN_NAMES = new Set(BUILT_IN_TOOLS.map((tool) => tool.name));
|
|
28
|
+
/** One Microsoft Teams call answered by one Deepgram Voice Agent. */
|
|
29
|
+
export class DeepgramHandler {
|
|
30
|
+
#config;
|
|
31
|
+
#tools;
|
|
32
|
+
#describer;
|
|
33
|
+
#connect;
|
|
34
|
+
#call;
|
|
35
|
+
#vision;
|
|
36
|
+
#callTools;
|
|
37
|
+
#agent;
|
|
38
|
+
#closed = false;
|
|
39
|
+
// Holds BOTH the caller's first words and the first context, so neither
|
|
40
|
+
// is lost while the provider is still connecting.
|
|
41
|
+
#pending = new StartupBuffer();
|
|
42
|
+
#caller = {
|
|
43
|
+
callerName: "the caller",
|
|
44
|
+
tenantId: "unknown-tenant",
|
|
45
|
+
direction: "inbound",
|
|
46
|
+
};
|
|
47
|
+
#notes = [];
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
this.#config = options.config ?? deepgramConfigFromEnv();
|
|
50
|
+
this.#tools = new Map((options.tools ?? []).map((tool) => [tool.name, tool]));
|
|
51
|
+
this.#describer = options.describer ?? FrameDescriber.fromEnv();
|
|
52
|
+
this.#connect = options.connect ?? AgentSocket.connect.bind(AgentSocket);
|
|
53
|
+
const collisions = [...this.#tools.keys()].filter((name) => BUILT_IN_NAMES.has(name));
|
|
54
|
+
if (collisions.length > 0) {
|
|
55
|
+
// Caught here rather than at the first call: a shadowed built-in is a
|
|
56
|
+
// call capability that silently stops working.
|
|
57
|
+
throw new Error(`custom tools may not shadow built-in ones: ${collisions.sort().join(", ")}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Whether the call is being recorded, straight off the session.
|
|
62
|
+
*
|
|
63
|
+
* The server keeps this current from `session.start` and every later
|
|
64
|
+
* `recording.status`, so there is nothing to re-derive here.
|
|
65
|
+
*/
|
|
66
|
+
#recording() {
|
|
67
|
+
return this.#call?.recordingActive ?? false;
|
|
68
|
+
}
|
|
69
|
+
// ---- the SDK seam -------------------------------------------------------
|
|
70
|
+
async onStart(session) {
|
|
71
|
+
this.#call = session;
|
|
72
|
+
this.#vision = new VisionTools(session, { describer: this.#describer });
|
|
73
|
+
this.#callTools = new CallTools(session, { vision: this.#vision });
|
|
74
|
+
const caller = session.start.caller;
|
|
75
|
+
this.#caller = {
|
|
76
|
+
callerName: caller.displayName ?? "the caller",
|
|
77
|
+
tenantId: caller.tenantId ?? "unknown-tenant",
|
|
78
|
+
direction: session.start.direction,
|
|
79
|
+
};
|
|
80
|
+
let agent;
|
|
81
|
+
try {
|
|
82
|
+
agent = await this.#connect(this.#config, (message) => this.#onAgentMessage(message), (pcm) => this.#onAgentAudio(pcm), (code, reason) => this.#onAgentClose(code, reason));
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
logger.error(`standin: could not open the Deepgram agent: ${String(err)}`);
|
|
86
|
+
await session.end("agent-unavailable");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// The call can end during the connect above.
|
|
90
|
+
if (this.#closed) {
|
|
91
|
+
await agent.aclose();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
this.#agent = agent;
|
|
95
|
+
const functions = [
|
|
96
|
+
...BUILT_IN_TOOLS,
|
|
97
|
+
...[...this.#tools.values()].map((tool) => ({
|
|
98
|
+
name: tool.name,
|
|
99
|
+
description: tool.description,
|
|
100
|
+
parameters: tool.parameters ?? {
|
|
101
|
+
type: "object",
|
|
102
|
+
properties: {},
|
|
103
|
+
required: [],
|
|
104
|
+
},
|
|
105
|
+
})),
|
|
106
|
+
];
|
|
107
|
+
agent.sendSettings(buildSettings(this.#config, buildPrompt(this.#config, this.#caller, this.#notes), functions));
|
|
108
|
+
await this.#pending.release((pcm) => agent.sendAudio(pcm), (text) => this.#noteContext(agent, text));
|
|
109
|
+
if (this.#pending.dropped.audio || this.#pending.dropped.context) {
|
|
110
|
+
logger.info("standin: the caller outran the agent starting up; some early input was dropped");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** The caller's voice, straight through as a binary frame. */
|
|
114
|
+
async onCallerAudio(pcm) {
|
|
115
|
+
const agent = this.#agent;
|
|
116
|
+
if (agent === undefined || !agent.isOpen) {
|
|
117
|
+
this.#pending.audio(pcm);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
agent.sendAudio(pcm);
|
|
121
|
+
}
|
|
122
|
+
/** Fold context into the prompt, because this API has nowhere else to put it. */
|
|
123
|
+
/**
|
|
124
|
+
* Keep a short history, so a question about a slide already gone can still be
|
|
125
|
+
* answered. Only kept while the call is recorded.
|
|
126
|
+
*/
|
|
127
|
+
async onVideoFrame(frame) {
|
|
128
|
+
this.#vision?.keyframes.offer(frame, this.#call?.recordingActive ?? false);
|
|
129
|
+
}
|
|
130
|
+
async onContext(text) {
|
|
131
|
+
const agent = this.#agent;
|
|
132
|
+
if (agent === undefined || !agent.isOpen) {
|
|
133
|
+
// Held rather than dropped: the "there are N people here, stay quiet"
|
|
134
|
+
// line and the recording change both land in this gap.
|
|
135
|
+
this.#pending.context(text);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.#noteContext(agent, text);
|
|
139
|
+
}
|
|
140
|
+
/** Fold one held context line into the prompt, once the agent exists. */
|
|
141
|
+
#noteContext(agent, text) {
|
|
142
|
+
this.#notes.push(text);
|
|
143
|
+
if (this.#notes.length > MAX_CONTEXT_NOTES)
|
|
144
|
+
this.#notes.shift();
|
|
145
|
+
agent.updatePrompt(buildPrompt(this.#config, this.#caller, this.#notes));
|
|
146
|
+
}
|
|
147
|
+
/** Say this line now, interrupting whatever the agent was saying. */
|
|
148
|
+
async onGoodbye(text) {
|
|
149
|
+
const agent = this.#agent;
|
|
150
|
+
if (agent !== undefined && agent.isOpen)
|
|
151
|
+
agent.injectAgentMessage(text);
|
|
152
|
+
}
|
|
153
|
+
async aclose() {
|
|
154
|
+
this.#closed = true;
|
|
155
|
+
const agent = this.#agent;
|
|
156
|
+
this.#agent = undefined;
|
|
157
|
+
if (agent !== undefined) {
|
|
158
|
+
try {
|
|
159
|
+
await agent.aclose();
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Teardown must not throw: the slot is freed either way.
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The shared vision tools for this call.
|
|
168
|
+
*
|
|
169
|
+
* They carry the budget, the keyframes and the graceful refusals, so this
|
|
170
|
+
* plugin no longer keeps its own copy of any of them.
|
|
171
|
+
*/
|
|
172
|
+
#visionTools() {
|
|
173
|
+
if (this.#vision === undefined)
|
|
174
|
+
throw new Error("the call has not started yet");
|
|
175
|
+
return this.#vision;
|
|
176
|
+
}
|
|
177
|
+
// ---- what Deepgram sends us ---------------------------------------------
|
|
178
|
+
/** Agent audio: already PCM16 at 16 kHz, so it goes straight out. */
|
|
179
|
+
async #onAgentAudio(pcm) {
|
|
180
|
+
if (pcm.length > 0)
|
|
181
|
+
await this.#call?.sendAudio(pcm);
|
|
182
|
+
}
|
|
183
|
+
async #onAgentMessage(message) {
|
|
184
|
+
switch (message.type) {
|
|
185
|
+
case "UserStartedSpeaking":
|
|
186
|
+
// Deepgram has decided the caller is talking. Flushing what StandIn has
|
|
187
|
+
// buffered is what actually stops the bot mid-word.
|
|
188
|
+
await this.#call?.cancelPlayback();
|
|
189
|
+
break;
|
|
190
|
+
case "FunctionCallRequest": {
|
|
191
|
+
const functions = message.functions;
|
|
192
|
+
if (Array.isArray(functions)) {
|
|
193
|
+
for (const fn of functions) {
|
|
194
|
+
if (typeof fn === "object" && fn !== null) {
|
|
195
|
+
void this.#runFunction(fn);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case "ConversationText":
|
|
202
|
+
if (this.#config.logTranscripts && this.#recording()) {
|
|
203
|
+
logger.info(`standin: deepgram ${String(message.role ?? "turn")}`);
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
case "Error":
|
|
207
|
+
case "Warning":
|
|
208
|
+
logger.warn(`standin: Deepgram ${message.type.toLowerCase()}: ` +
|
|
209
|
+
String(message.description ?? message.code ?? "no detail"));
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async #onAgentClose(code, reason) {
|
|
216
|
+
logger.info(`standin: the Deepgram agent closed (${code} ${reason})`);
|
|
217
|
+
if (!this.#closed)
|
|
218
|
+
await this.#call?.end("agent-disconnected");
|
|
219
|
+
}
|
|
220
|
+
// ---- the agent's functions ----------------------------------------------
|
|
221
|
+
async #runFunction(fn) {
|
|
222
|
+
const name = fn.name;
|
|
223
|
+
const callId = fn.id;
|
|
224
|
+
if (typeof name !== "string" || typeof callId !== "string")
|
|
225
|
+
return;
|
|
226
|
+
let params = {};
|
|
227
|
+
if (typeof fn.arguments === "string") {
|
|
228
|
+
try {
|
|
229
|
+
const parsed = JSON.parse(fn.arguments || "{}");
|
|
230
|
+
if (typeof parsed === "object" && parsed !== null)
|
|
231
|
+
params = parsed;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
params = {};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (typeof fn.arguments === "object" && fn.arguments !== null) {
|
|
238
|
+
params = fn.arguments;
|
|
239
|
+
}
|
|
240
|
+
let result;
|
|
241
|
+
try {
|
|
242
|
+
result = await this.dispatch(name, params);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
// Tell the agent the truth. A tool that silently "succeeded" leaves it
|
|
246
|
+
// talking about something that never happened.
|
|
247
|
+
result = `${name} failed: ${String(err)}`;
|
|
248
|
+
}
|
|
249
|
+
this.#agent?.sendFunctionResult(callId, name, result);
|
|
250
|
+
}
|
|
251
|
+
/** Run one function and return what the agent is told. Exposed for tests. */
|
|
252
|
+
async dispatch(name, params) {
|
|
253
|
+
const call = this.#call;
|
|
254
|
+
if (call === undefined)
|
|
255
|
+
return "the call is no longer active";
|
|
256
|
+
const callTools = this.#callTools;
|
|
257
|
+
if (callTools !== undefined && BUILT_IN_NAMES.has(name)) {
|
|
258
|
+
// The SDK owns these, and its dispatch never throws: what comes back is
|
|
259
|
+
// the sentence the agent should say.
|
|
260
|
+
return callTools.dispatch(name, params);
|
|
261
|
+
}
|
|
262
|
+
const tool = this.#tools.get(name);
|
|
263
|
+
if (tool === undefined)
|
|
264
|
+
return `"${name}" is not a tool this plugin answers`;
|
|
265
|
+
return String(await tool.handler(params, { call, recording: this.#recording() }));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/plugins/deepgram/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { AgentSocket, WIRE_SAMPLE_RATE_HZ, buildPrompt, buildSettings, type AgentMessage, type AgentPort, type CallerContext, } from "./agent.js";
|
|
2
|
+
export { DEFAULT_INSTRUCTIONS, deepgramConfigFromEnv, type DeepgramConfig, } from "./config.js";
|
|
3
|
+
export { BUILT_IN_TOOLS, DeepgramHandler, type Connect, type CustomTool, type DeepgramHandlerOptions, type ToolContext, } from "./handler.js";
|
|
4
|
+
/**
|
|
5
|
+
* Answer Microsoft Teams calls with Deepgram until the process is interrupted.
|
|
6
|
+
*
|
|
7
|
+
* The configuration is read ONCE here: a missing API key should stop the worker
|
|
8
|
+
* at startup, not surprise the first caller.
|
|
9
|
+
*/
|
|
10
|
+
export declare function serve(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/deepgram/index.ts"],"names":[],"mappings":"AAsDA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,eAAe,EACf,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB3C"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright (c) 2026 Komaa DigiTech
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* Answer Microsoft Teams calls with a Deepgram Voice Agent.
|
|
5
|
+
*
|
|
6
|
+
* StandIn answers the Microsoft Teams call and dials this worker. This
|
|
7
|
+
* plugin answers that dial, opens one Voice Agent session per call, and
|
|
8
|
+
* relays the audio both ways.
|
|
9
|
+
*
|
|
10
|
+
* Nothing to install beyond the SDK: Deepgram 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 DEEPGRAM_API_KEY=...
|
|
18
|
+
* npx standin-deepgram
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Speech to text, reasoning and speech are all configured on the session, so
|
|
22
|
+
* there is nothing to set up on the Deepgram side. Audio is pinned to linear16
|
|
23
|
+
* at 16 kHz in both directions, which is exactly what StandIn speaks.
|
|
24
|
+
*
|
|
25
|
+
* The agent gets four call capabilities without any configuration: `end_call`,
|
|
26
|
+
* `express`, `show_image` and `look`. Looking needs a vision model, because a
|
|
27
|
+
* Voice Agent hears but does not see - set `STANDIN_VISION_API_URL` and
|
|
28
|
+
* `STANDIN_VISION_MODEL` to any OpenAI-compatible endpoint that takes images.
|
|
29
|
+
*
|
|
30
|
+
* Add tools of your own, executed in your worker:
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { CallServer } from "@komaa/standin-sdk";
|
|
34
|
+
* import { DeepgramHandler } from "@komaa/standin-sdk/deepgram";
|
|
35
|
+
*
|
|
36
|
+
* const tools = [{
|
|
37
|
+
* name: "open_ticket",
|
|
38
|
+
* description: "Open a support ticket for the caller.",
|
|
39
|
+
* parameters: { type: "object", properties: { summary: { type: "string" } }, required: ["summary"] },
|
|
40
|
+
* handler: async (params) => `opened ticket for ${String(params.summary)}`,
|
|
41
|
+
* }];
|
|
42
|
+
*
|
|
43
|
+
* const server = new CallServer({ handlerFactory: () => new DeepgramHandler({ tools }) });
|
|
44
|
+
* await server.start();
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* The Python twin is `standin.plugins.deepgram`.
|
|
48
|
+
*/
|
|
49
|
+
import { CallServer } from "../../index.js";
|
|
50
|
+
import { DeepgramHandler } from "./handler.js";
|
|
51
|
+
import { deepgramConfigFromEnv } from "./config.js";
|
|
52
|
+
export { AgentSocket, WIRE_SAMPLE_RATE_HZ, buildPrompt, buildSettings, } from "./agent.js";
|
|
53
|
+
export { DEFAULT_INSTRUCTIONS, deepgramConfigFromEnv, } from "./config.js";
|
|
54
|
+
export { BUILT_IN_TOOLS, DeepgramHandler, } from "./handler.js";
|
|
55
|
+
/**
|
|
56
|
+
* Answer Microsoft Teams calls with Deepgram until the process is interrupted.
|
|
57
|
+
*
|
|
58
|
+
* The configuration is read ONCE here: a missing API key should stop the worker
|
|
59
|
+
* at startup, not surprise the first caller.
|
|
60
|
+
*/
|
|
61
|
+
export async function serve() {
|
|
62
|
+
const config = deepgramConfigFromEnv();
|
|
63
|
+
const server = new CallServer({
|
|
64
|
+
handlerFactory: () => new DeepgramHandler({ config }),
|
|
65
|
+
});
|
|
66
|
+
await server.start();
|
|
67
|
+
await new Promise((resolve) => {
|
|
68
|
+
const stop = () => {
|
|
69
|
+
resolve();
|
|
70
|
+
};
|
|
71
|
+
process.once("SIGINT", stop);
|
|
72
|
+
process.once("SIGTERM", stop);
|
|
73
|
+
});
|
|
74
|
+
await server.aclose();
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/deepgram/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,+BAA+B;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;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,WAAW,EACX,aAAa,GAId,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GAEtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,eAAe,GAKhB,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,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 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/plugins/echo/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-echo` */
|
|
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/echo/cli.ts"],"names":[],"mappings":";AACA,oCAAoC;AACpC,+BAA+B;AAE/B,yBAAyB;AAEzB,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,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The smallest StandIn plugin that answers a real Microsoft Teams call.
|
|
3
|
+
*
|
|
4
|
+
* Copy this directory to start a new plugin. It has no dependency beyond
|
|
5
|
+
* the SDK core and it works: call the number, talk, and hear yourself back. That
|
|
6
|
+
* makes it a useful thing to run before you suspect your own agent - if the echo
|
|
7
|
+
* answers, your secret, your tunnel and your StandIn identity are all correct.
|
|
8
|
+
*
|
|
9
|
+
* ```bash
|
|
10
|
+
* npm install @komaa/standin-sdk
|
|
11
|
+
* STANDIN_SECRET=... npx standin-echo
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* To make it a real plugin, replace {@link EchoHandler.onCallerAudio} with
|
|
15
|
+
* your framework's agent loop. Everything else here is the shape every
|
|
16
|
+
* plugin keeps.
|
|
17
|
+
*
|
|
18
|
+
* The Python twin of this file is `standin.plugins.echo`; the two are the
|
|
19
|
+
* same handler with the same method names in each language's casing.
|
|
20
|
+
*/
|
|
21
|
+
import { type CallSession } from "../../index.js";
|
|
22
|
+
/**
|
|
23
|
+
* One instance per call. Sends the caller's own voice back to them.
|
|
24
|
+
*
|
|
25
|
+
* A handler implements only what it needs: the SDK treats every callback as
|
|
26
|
+
* optional, so this class defines three of the five and the other two are
|
|
27
|
+
* no-ops. Nothing extends anything.
|
|
28
|
+
*/
|
|
29
|
+
export declare class EchoHandler {
|
|
30
|
+
#private;
|
|
31
|
+
onStart(session: CallSession): Promise<void>;
|
|
32
|
+
onCallerAudio(pcm: Buffer): Promise<void>;
|
|
33
|
+
onGoodbye(text: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/** Answer Microsoft Teams calls until the process is interrupted. */
|
|
36
|
+
export declare function serve(): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|