@mastra/livekit 0.0.0-buttoned-spandex-20260824090603
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/CHANGELOG.md +433 -0
- package/LICENSE.md +30 -0
- package/README.md +448 -0
- package/dist/bridge.d.ts +229 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/consent.d.ts +55 -0
- package/dist/consent.d.ts.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/dispatch.d.ts +20 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/end-call.d.ts +50 -0
- package/dist/end-call.d.ts.map +1 -0
- package/dist/index.cjs +189 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-plugin.d.ts +112 -0
- package/dist/llm-plugin.d.ts.map +1 -0
- package/dist/messages.d.ts +50 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/metadata.d.ts +17 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/observability.d.ts +46 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/plugin-entry.cjs +209 -0
- package/dist/plugin-entry.cjs.map +1 -0
- package/dist/plugin-entry.d.ts +6 -0
- package/dist/plugin-entry.d.ts.map +1 -0
- package/dist/plugin-entry.js +207 -0
- package/dist/plugin-entry.js.map +1 -0
- package/dist/remote-C9K3UzKv.js +629 -0
- package/dist/remote-C9K3UzKv.js.map +1 -0
- package/dist/remote-D0Y5P6e4.cjs +658 -0
- package/dist/remote-D0Y5P6e4.cjs.map +1 -0
- package/dist/remote.d.ts +68 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/routes.d.ts +52 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/run.d.ts +32 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/voice-thread.d.ts +23 -0
- package/dist/voice-thread.d.ts.map +1 -0
- package/dist/worker-entry.cjs +686 -0
- package/dist/worker-entry.cjs.map +1 -0
- package/dist/worker-entry.d.ts +10 -0
- package/dist/worker-entry.d.ts.map +1 -0
- package/dist/worker-entry.js +675 -0
- package/dist/worker-entry.js.map +1 -0
- package/dist/worker-setup.d.ts +5 -0
- package/dist/worker-setup.d.ts.map +1 -0
- package/dist/worker.d.ts +461 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/workflow-generator-B67QrY8L.cjs +209 -0
- package/dist/workflow-generator-B67QrY8L.cjs.map +1 -0
- package/dist/workflow-generator-BtfClQcM.js +180 -0
- package/dist/workflow-generator-BtfClQcM.js.map +1 -0
- package/dist/workflow-generator.d.ts +92 -0
- package/dist/workflow-generator.d.ts.map +1 -0
- package/package.json +107 -0
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { ReadableStream } from 'node:stream/web';
|
|
2
|
+
import { llm, voice } from '@livekit/agents';
|
|
3
|
+
import type { Agent as MastraAgent, AgentExecutionOptionsBase } from '@mastra/core/agent';
|
|
4
|
+
import type { TracingContext } from '@mastra/core/observability';
|
|
5
|
+
import { RequestContext } from '@mastra/core/request-context';
|
|
6
|
+
import type { VoiceTurnMessage } from './messages.js';
|
|
7
|
+
/** Default spoken text for periodic AI re-disclosure. See {@link MastraVoiceAgentOptions.greetingReminder}. */
|
|
8
|
+
export declare const DEFAULT_DISCLOSURE_REMINDER = "Just a reminder, you're speaking with an AI assistant.";
|
|
9
|
+
/**
|
|
10
|
+
* Tracks periodic AI re-disclosure for a single call. `due()` returns the reminder text once
|
|
11
|
+
* `everyMs` has elapsed since the last disclosure (resetting the clock), otherwise `undefined`.
|
|
12
|
+
* Time is injectable so the interval logic is deterministically testable.
|
|
13
|
+
*/
|
|
14
|
+
export declare class DisclosureReminder {
|
|
15
|
+
private readonly everyMs;
|
|
16
|
+
private readonly text;
|
|
17
|
+
private lastAt;
|
|
18
|
+
constructor(everyMs: number, text: string, now?: number);
|
|
19
|
+
/** Call once per turn: the reminder text if it's due, else `undefined`. Does not reset the clock —
|
|
20
|
+
* call {@link DisclosureReminder.markDelivered} once the reminder is actually threaded into the
|
|
21
|
+
* outgoing reply, so a reminder that never makes it out isn't silently skipped for a full interval. */
|
|
22
|
+
due(now?: number): string | undefined;
|
|
23
|
+
/** Resets the clock. Call only once the reminder text from {@link due} was actually emitted. */
|
|
24
|
+
markDelivered(now?: number): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Wraps `source` in a stream that emits `text` as a single leading chunk (with a trailing space, so
|
|
28
|
+
* TTS pauses before the reply) before piping the rest of `source` through unchanged. Cancelling the
|
|
29
|
+
* wrapper cancels `source` — so barge-in still aborts the underlying generation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function prependText(source: ReadableStream<string>, text: string): ReadableStream<string>;
|
|
32
|
+
export type MastraStreamOptions = Partial<AgentExecutionOptionsBase<unknown>>;
|
|
33
|
+
export interface VoiceToolCall {
|
|
34
|
+
toolCallId: string;
|
|
35
|
+
toolName: string;
|
|
36
|
+
args?: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Token usage for one turn, captured from the model's `finish` chunk. Field names mirror LiveKit's
|
|
40
|
+
* `CompletionUsage` so the plugin can forward it into `metrics_collected` without remapping.
|
|
41
|
+
*/
|
|
42
|
+
export interface VoiceTurnUsage {
|
|
43
|
+
/** Tokens in the prompt (LiveKit `promptTokens`). */
|
|
44
|
+
promptTokens: number;
|
|
45
|
+
/** Tokens in the completion (LiveKit `completionTokens`). */
|
|
46
|
+
completionTokens: number;
|
|
47
|
+
/** Cached prompt tokens (LiveKit `promptCachedTokens`). */
|
|
48
|
+
promptCachedTokens: number;
|
|
49
|
+
/** Total tokens for the turn. */
|
|
50
|
+
totalTokens: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Maps a Mastra `finish` chunk's usage (`payload.output.usage`, AI-SDK `LanguageModelUsage`) to the
|
|
54
|
+
* LiveKit-shaped {@link VoiceTurnUsage}, or `undefined` when the chunk carries no token counts.
|
|
55
|
+
* Handles both the flat V2 usage shape (`inputTokens`/`outputTokens`) and the nested V3 shape
|
|
56
|
+
* (`inputTokens.total`/`outputTokens.total`).
|
|
57
|
+
*/
|
|
58
|
+
export declare function mapTurnUsage(usage: unknown): VoiceTurnUsage | undefined;
|
|
59
|
+
export interface MastraVoiceAgentMemory {
|
|
60
|
+
thread: string;
|
|
61
|
+
resource?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Per-turn context handed to a {@link VoiceReplyGenerator}. LiveKit calls `llmNode` once per
|
|
65
|
+
* detected user turn; the bridge builds this context and asks the generator for the reply.
|
|
66
|
+
*/
|
|
67
|
+
export interface VoiceTurnContext {
|
|
68
|
+
/**
|
|
69
|
+
* The messages to generate a reply from. With Mastra Memory on, only the messages new since
|
|
70
|
+
* the agent last spoke (history comes from the thread); with memory off, the full session.
|
|
71
|
+
*
|
|
72
|
+
* For a workflow / custom generator: pass these straight to a memory-backed `agent.stream(...,
|
|
73
|
+
* { memory })` inside a step so the agent backfills history from the thread (no duplication). A
|
|
74
|
+
* stateless workflow that wants the entire transcript every turn should read `chatCtx` instead
|
|
75
|
+
* (e.g. `chatContextToMessages(chatCtx)`), since there is no thread to backfill from.
|
|
76
|
+
*/
|
|
77
|
+
messages: VoiceTurnMessage[];
|
|
78
|
+
/** The raw LiveKit chat context, for generators that want the full transcript or message parts. */
|
|
79
|
+
chatCtx: llm.ChatContext;
|
|
80
|
+
/** Resolved memory mapping for the call, or `false` when memory is disabled. */
|
|
81
|
+
memory: MastraVoiceAgentMemory | false;
|
|
82
|
+
/** Request context forwarded to generation. */
|
|
83
|
+
requestContext?: RequestContext;
|
|
84
|
+
/** Voice-call span context, so each turn's generation nests under the call trace. */
|
|
85
|
+
tracingContext?: TracingContext;
|
|
86
|
+
/**
|
|
87
|
+
* Internal, per-turn side channel for token usage. A generator invokes this once, when the
|
|
88
|
+
* `finish` chunk carries usage, so the caller (e.g. `MastraLLMStream`) can attribute usage to
|
|
89
|
+
* exactly this turn — kept on the context (not on generator options) so overlapping turns from
|
|
90
|
+
* preemptive generation can't misattribute usage. Fire-and-forget; the generator does not await it.
|
|
91
|
+
*/
|
|
92
|
+
onUsage?: (usage: VoiceTurnUsage) => void;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* What a turn produced, handed to {@link VoiceTurnCompleteHook} after the reply finishes.
|
|
96
|
+
*/
|
|
97
|
+
export interface VoiceTurnResult {
|
|
98
|
+
/** The assistant reply text streamed this turn, accumulated from the model's text deltas. */
|
|
99
|
+
text: string;
|
|
100
|
+
/** Tool calls the agent made during the turn, in order. */
|
|
101
|
+
toolCalls: VoiceToolCall[];
|
|
102
|
+
/** True when barge-in cut the turn short before it finished streaming. */
|
|
103
|
+
interrupted: boolean;
|
|
104
|
+
/** Token usage for the turn when the model reported it in its `finish` chunk. */
|
|
105
|
+
usage?: VoiceTurnUsage;
|
|
106
|
+
}
|
|
107
|
+
/** {@link VoiceTurnContext} plus the reply it produced. Passed to {@link VoiceTurnCompleteHook}. */
|
|
108
|
+
export interface VoiceTurnCompleteContext extends VoiceTurnContext {
|
|
109
|
+
/** The reply the agent produced this turn. */
|
|
110
|
+
result: VoiceTurnResult;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Called once per turn AFTER the reply has finished streaming to text-to-speech — off the audio
|
|
114
|
+
* path. It runs fire-and-forget: the turn does not await it, so post-turn work (memory
|
|
115
|
+
* maintenance, CRM writes, analytics) never delays what the caller hears or the next turn. A
|
|
116
|
+
* thrown error or rejected promise is logged, not propagated. Because the resolved `memory`
|
|
117
|
+
* mapping (`thread`/`resource`) is on the context, this is the place for a truly non-blocking
|
|
118
|
+
* `memory.updateWorkingMemory(...)`. See {@link MastraVoiceAgentOptions.onTurnComplete}.
|
|
119
|
+
*/
|
|
120
|
+
export type VoiceTurnCompleteHook = (ctx: VoiceTurnCompleteContext) => void | Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Produces a stream of text deltas for one conversational turn, or `null` to stay silent.
|
|
123
|
+
* Cancelling the returned stream (LiveKit does this on barge-in) must abort the underlying
|
|
124
|
+
* generation. Built-in implementations: {@link createAgentReplyGenerator} (a Mastra agent) and
|
|
125
|
+
* `createWorkflowReplyGenerator` (a Mastra workflow).
|
|
126
|
+
*/
|
|
127
|
+
export type VoiceReplyGenerator = (ctx: VoiceTurnContext) => ReadableStream<string> | null | Promise<ReadableStream<string> | null>;
|
|
128
|
+
export interface AgentReplyGeneratorOptions {
|
|
129
|
+
/** The Mastra agent that generates replies. Tools and memory run inside this agent. */
|
|
130
|
+
agent: MastraAgent;
|
|
131
|
+
/** Extra options merged into every `agent.stream()` call (e.g. `tracingContext`). */
|
|
132
|
+
streamOptions?: MastraStreamOptions;
|
|
133
|
+
/** Speak a short phrase while a tool call runs. See {@link MastraVoiceAgentOptions.toolFeedback}. */
|
|
134
|
+
toolFeedback?: (toolCall: VoiceToolCall) => string | undefined | void;
|
|
135
|
+
/** Notified as each tool-call chunk arrives, mid-stream. See {@link MastraVoiceAgentOptions.onToolCall}. */
|
|
136
|
+
onToolCall?: (toolCall: VoiceToolCall) => void;
|
|
137
|
+
/** Fired off the audio path after the reply streams. See {@link MastraVoiceAgentOptions.onTurnComplete}. */
|
|
138
|
+
onTurnComplete?: VoiceTurnCompleteHook;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A {@link VoiceReplyGenerator} backed by a Mastra agent: runs the agent's full loop (model,
|
|
142
|
+
* tools, memory) and streams its text deltas. On barge-in the returned stream is cancelled,
|
|
143
|
+
* which aborts the in-flight `agent.stream()`.
|
|
144
|
+
*/
|
|
145
|
+
export declare function createAgentReplyGenerator(options: AgentReplyGeneratorOptions): VoiceReplyGenerator;
|
|
146
|
+
export interface MastraVoiceAgentOptions {
|
|
147
|
+
/**
|
|
148
|
+
* The Mastra agent that generates replies. Tools and memory run inside this agent. Provide
|
|
149
|
+
* either this or {@link MastraVoiceAgentOptions.generate}.
|
|
150
|
+
*/
|
|
151
|
+
agent?: MastraAgent;
|
|
152
|
+
/**
|
|
153
|
+
* A lower-level reply generator (e.g. from `createWorkflowReplyGenerator`). Use instead of
|
|
154
|
+
* `agent` to drive replies with a workflow or any custom generator.
|
|
155
|
+
*/
|
|
156
|
+
generate?: VoiceReplyGenerator;
|
|
157
|
+
/**
|
|
158
|
+
* Conversation persistence. When set, only messages new since the agent last spoke are
|
|
159
|
+
* sent each turn and Mastra Memory supplies history. When `false`, the full LiveKit
|
|
160
|
+
* in-session context is sent on every turn instead.
|
|
161
|
+
*/
|
|
162
|
+
memory?: MastraVoiceAgentMemory | false;
|
|
163
|
+
/** Request context entries forwarded to generation. */
|
|
164
|
+
requestContext?: RequestContext | Record<string, unknown>;
|
|
165
|
+
/**
|
|
166
|
+
* Called when the Mastra agent starts a tool call mid-reply. Return a short phrase (e.g. "Let
|
|
167
|
+
* me look that up.") to speak it while the tool runs; it also appears in the transcript. Return
|
|
168
|
+
* nothing to stay silent. Applies to the agent generator built here; the workflow generator
|
|
169
|
+
* takes its own equivalent via `createWorkflowReplyGenerator`.
|
|
170
|
+
*/
|
|
171
|
+
toolFeedback?: (toolCall: VoiceToolCall) => string | undefined | void;
|
|
172
|
+
/**
|
|
173
|
+
* Called as each tool call starts mid-reply (before the tool result is known), the building block
|
|
174
|
+
* for tool-driven side effects — analytics, agent-initiated hang-up — without waiting for the turn
|
|
175
|
+
* to finish. Runs synchronously on the stream; keep it cheap and non-throwing. Applies to the agent
|
|
176
|
+
* generator built here; the workflow generator surfaces tool calls via `onTurnComplete` instead.
|
|
177
|
+
*/
|
|
178
|
+
onToolCall?: (toolCall: VoiceToolCall) => void;
|
|
179
|
+
/**
|
|
180
|
+
* Called once per turn after the reply has finished streaming to text-to-speech. Runs off the
|
|
181
|
+
* audio path and fire-and-forget — the turn does not await it — so post-turn memory
|
|
182
|
+
* maintenance, CRM writes, or analytics never delay the caller or the next turn. The context
|
|
183
|
+
* carries the produced reply ({@link VoiceTurnResult}) and the resolved `memory` mapping, so
|
|
184
|
+
* this is where a truly non-blocking `memory.updateWorkingMemory(...)` belongs. A thrown error
|
|
185
|
+
* or rejected promise is logged, not propagated. Applies to the agent generator built here; the
|
|
186
|
+
* workflow generator takes its own via `createWorkflowReplyGenerator`.
|
|
187
|
+
*/
|
|
188
|
+
onTurnComplete?: VoiceTurnCompleteHook;
|
|
189
|
+
/**
|
|
190
|
+
* Periodic AI re-disclosure. When set, once `everyMs` has elapsed since the last disclosure the
|
|
191
|
+
* NEXT turn's reply is prefixed with `text` (spoken at the turn boundary, never mid-turn), so long
|
|
192
|
+
* calls keep re-disclosing the AI status. Applies to the agent and workflow/custom generators. The
|
|
193
|
+
* worker derives this from `configuration.greeting.repeatEvery` / `repeatText`; `text` defaults to
|
|
194
|
+
* {@link DEFAULT_DISCLOSURE_REMINDER}.
|
|
195
|
+
*/
|
|
196
|
+
greetingReminder?: {
|
|
197
|
+
everyMs: number;
|
|
198
|
+
text?: string;
|
|
199
|
+
};
|
|
200
|
+
/** Extra options merged into every `agent.stream()` call (agent generator only). */
|
|
201
|
+
streamOptions?: MastraStreamOptions;
|
|
202
|
+
/** LiveKit agent instructions. Unused for reply generation (the Mastra agent/workflow applies its own). */
|
|
203
|
+
instructions?: string;
|
|
204
|
+
id?: voice.AgentOptions<unknown>['id'];
|
|
205
|
+
stt?: voice.AgentOptions<unknown>['stt'];
|
|
206
|
+
vad?: voice.AgentOptions<unknown>['vad'];
|
|
207
|
+
tts?: voice.AgentOptions<unknown>['tts'];
|
|
208
|
+
turnHandling?: voice.AgentOptions<unknown>['turnHandling'];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A LiveKit `voice.Agent` whose replies come from a Mastra agent or workflow.
|
|
212
|
+
*
|
|
213
|
+
* LiveKit keeps ownership of the audio loop (VAD, STT, turn detection, TTS, barge-in) and calls
|
|
214
|
+
* `llmNode` once per detected user turn; the node delegates to a {@link VoiceReplyGenerator}
|
|
215
|
+
* which streams text deltas back. On barge-in LiveKit cancels the returned stream, which aborts
|
|
216
|
+
* the in-flight generation.
|
|
217
|
+
*/
|
|
218
|
+
export declare class MastraVoiceAgent extends voice.Agent {
|
|
219
|
+
readonly mastraAgent?: MastraAgent;
|
|
220
|
+
readonly memory: MastraVoiceAgentMemory | false;
|
|
221
|
+
readonly requestContext?: RequestContext;
|
|
222
|
+
readonly streamOptions?: MastraStreamOptions;
|
|
223
|
+
private readonly replyGenerator;
|
|
224
|
+
private readonly reminder?;
|
|
225
|
+
constructor(options: MastraVoiceAgentOptions);
|
|
226
|
+
llmNode(chatCtx: llm.ChatContext, _toolCtx: llm.ToolContext, _modelSettings: voice.ModelSettings): Promise<ReadableStream<llm.ChatChunk | string> | null>;
|
|
227
|
+
}
|
|
228
|
+
export declare function createMastraVoiceAgent(options: MastraVoiceAgentOptions): MastraVoiceAgent;
|
|
229
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,KAAK,IAAI,WAAW,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,+GAA+G;AAC/G,eAAO,MAAM,2BAA2B,2DAA2D,CAAC;AAEpG;;;;GAIG;AACH,qBAAa,kBAAkB;IAG3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,MAAM,CAAS;gBAEJ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAC7B,GAAG,GAAE,MAAmB;IAI1B;;2GAEuG;IACvG,GAAG,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM,GAAG,SAAS;IAIjD,gGAAgG;IAChG,aAAa,CAAC,GAAG,GAAE,MAAmB,GAAG,IAAI;CAG9C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAoBhG;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CA2BvE;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mGAAmG;IACnG,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC;IACzB,gFAAgF;IAChF,MAAM,EAAE,sBAAsB,GAAG,KAAK,CAAC;IACvC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qFAAqF;IACrF,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;IACrB,iFAAiF;IACjF,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,oGAAoG;AACpG,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,8CAA8C;IAC9C,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5F;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,GAAG,EAAE,gBAAgB,KAClB,cAAc,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AAE5E,MAAM,WAAW,0BAA0B;IACzC,uFAAuF;IACvF,KAAK,EAAE,WAAW,CAAC;IACnB,qFAAqF;IACrF,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,qGAAqG;IACrG,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACtE,4GAA4G;IAC5G,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,4GAA4G;IAC5G,cAAc,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,mBAAmB,CAyGlG;AAED,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B;;;;OAIG;IACH,MAAM,CAAC,EAAE,sBAAsB,GAAG,KAAK,CAAC;IACxC,uDAAuD;IACvD,cAAc,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACtE;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,oFAAoF;IACpF,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,2GAA2G;IAC3G,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC;CAC5D;AAiCD;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,KAAK,CAAC,KAAK;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,sBAAsB,GAAG,KAAK,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAqB;gBAEnC,OAAO,EAAE,uBAAuB;IAyC7B,OAAO,CACpB,OAAO,EAAE,GAAG,CAAC,WAAW,EACxB,QAAQ,EAAE,GAAG,CAAC,WAAW,EACzB,cAAc,EAAE,KAAK,CAAC,aAAa,GAClC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC;CA2B1D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CAEzF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** A consent decision captured from the caller during a call. */
|
|
2
|
+
export interface ConsentGrant {
|
|
3
|
+
/**
|
|
4
|
+
* The consent item, matching a key in the worker's `configuration.consentPolicy` (e.g.
|
|
5
|
+
* `'summaryStorage'`).
|
|
6
|
+
*/
|
|
7
|
+
item: string;
|
|
8
|
+
/** `true` if the caller agreed, `false` if they declined. */
|
|
9
|
+
granted: boolean;
|
|
10
|
+
/** The caller the grant belongs to (the memory `resource`), when the call is memory-scoped. */
|
|
11
|
+
resourceId?: string;
|
|
12
|
+
/** The call thread the grant was captured on, when the call is memory-scoped. */
|
|
13
|
+
threadId?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ConsentToolOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Persist the caller's decision to YOUR system of record (database, CRM, consent ledger). Called
|
|
18
|
+
* each time the caller answers a consent question — keep it quick, it runs inside the turn. This
|
|
19
|
+
* tool owns extracting the caller's identity from the tool execution context; you own storage, so
|
|
20
|
+
* consent lives in a durable, compliant place rather than an opaque plugin store. Read those
|
|
21
|
+
* grants back at `onCallEnd` (or before any consent-gated step) to enforce the requirement.
|
|
22
|
+
*/
|
|
23
|
+
onGrant: (grant: ConsentGrant) => void | Promise<void>;
|
|
24
|
+
/** Tool id the agent calls. Defaults to `'recordConsent'`. */
|
|
25
|
+
id?: string;
|
|
26
|
+
/** Override the description the model sees when deciding to call the tool. */
|
|
27
|
+
description?: string;
|
|
28
|
+
/** Restrict the accepted consent items to this set (becomes an enum). Defaults to any string. */
|
|
29
|
+
items?: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds a Mastra tool that captures the caller's consent decisions at runtime — the companion to
|
|
33
|
+
* the worker's `configuration.consentPolicy`, which only DECLARES which consents a call needs. Add
|
|
34
|
+
* it to the agent that answers the call; on each call the tool reads the caller's `resourceId` /
|
|
35
|
+
* `threadId` from its execution context and hands the decision to your `onGrant` store. The runtime
|
|
36
|
+
* grants live only where `onGrant` put them: enforce consent by reading them back from your own
|
|
37
|
+
* store — at `onCallEnd` or before any consent-gated action — cross-checking against the declared
|
|
38
|
+
* requirements in `VoiceCallEndArgs.configuration.consentPolicy` (the configuration carries the
|
|
39
|
+
* policy, never the grants).
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* // agent tools
|
|
43
|
+
* recordConsent: createConsentTool({
|
|
44
|
+
* items: ['summaryStorage'],
|
|
45
|
+
* onGrant: async ({ item, granted, resourceId }) => {
|
|
46
|
+
* if (resourceId) await db.saveConsent(resourceId, item, granted);
|
|
47
|
+
* },
|
|
48
|
+
* }),
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function createConsentTool(options: ConsentToolOptions): import("@mastra/core/tools").Tool<{
|
|
52
|
+
item: string;
|
|
53
|
+
granted: boolean;
|
|
54
|
+
}, unknown, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, string, unknown>;
|
|
55
|
+
//# sourceMappingURL=consent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../src/consent.ts"],"names":[],"mappings":"AAMA,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,+FAA+F;IAC/F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB;;;6HAiB5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LiveKitSessionMetadata } from './metadata.js';
|
|
2
|
+
export interface DispatchVoiceSessionOptions {
|
|
3
|
+
/** Room to dispatch the agent into (created on demand). */
|
|
4
|
+
roomName: string;
|
|
5
|
+
/** Must match the worker's `agentName`. Defaults to `'mastra-voice'`. */
|
|
6
|
+
agentName?: string;
|
|
7
|
+
metadata?: LiveKitSessionMetadata;
|
|
8
|
+
/** Defaults to `LIVEKIT_URL`. */
|
|
9
|
+
serverUrl?: string;
|
|
10
|
+
/** Defaults to `LIVEKIT_API_KEY`. */
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
/** Defaults to `LIVEKIT_API_SECRET`. */
|
|
13
|
+
apiSecret?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Programmatically dispatches a Mastra voice agent into a LiveKit room — for
|
|
17
|
+
* server-initiated sessions such as outbound calls or joining an existing room.
|
|
18
|
+
*/
|
|
19
|
+
export declare function dispatchVoiceSession(options: DispatchVoiceSessionOptions): Promise<import("livekit-server-sdk").AgentDispatch>;
|
|
20
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,2BAA2B;IAC1C,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,uDAgB9E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Details of the agent's decision to end the call, handed to {@link EndCallToolOptions.onEndCall}. */
|
|
2
|
+
export interface EndCallRequest {
|
|
3
|
+
/** Short reason the agent gave for ending the call, if any (e.g. "caller said goodbye"). */
|
|
4
|
+
reason?: string;
|
|
5
|
+
/** The caller the call belongs to (the memory `resource`), when the call is memory-scoped. */
|
|
6
|
+
resourceId?: string;
|
|
7
|
+
/** The call thread, when the call is memory-scoped. */
|
|
8
|
+
threadId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EndCallToolOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Tool id the agent calls to end the call. Must match the worker's
|
|
13
|
+
* `configuration.endCall.tool` (both default to `'endCall'`), since that's the name the worker
|
|
14
|
+
* watches for to hang up.
|
|
15
|
+
*/
|
|
16
|
+
id?: string;
|
|
17
|
+
/** Override the description the model sees when deciding to call the tool. */
|
|
18
|
+
description?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Optional bookkeeping hook, called when the agent invokes the tool (records the reason, marks
|
|
21
|
+
* the call resolved in your CRM, …). Runs inside the turn — keep it quick. It does NOT hang up
|
|
22
|
+
* the call; the worker does that once the agent's final words finish playing. The tool reads the
|
|
23
|
+
* caller's identity from its execution context and passes it here.
|
|
24
|
+
*/
|
|
25
|
+
onEndCall?: (request: EndCallRequest) => void | Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Builds a Mastra tool the agent calls to end the call itself (say goodbye → hang up). It is the
|
|
29
|
+
* agent-visible half of agent-initiated hang-up: the tool only SIGNALS intent (and runs optional
|
|
30
|
+
* bookkeeping) — it can't reach the LiveKit room from inside `agent.stream()`. The worker owns the
|
|
31
|
+
* hang-up: with `configuration.endCall` set, it watches each turn for this tool, waits for the
|
|
32
|
+
* agent's closing words to finish playing, then disconnects (running `onCallEnd` on the way out).
|
|
33
|
+
* Keeping the tool inside the single agent means it stays visible/editable in Studio and works on
|
|
34
|
+
* the agent and workflow reply paths alike.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* // agent tools
|
|
38
|
+
* endCall: createEndCallTool({
|
|
39
|
+
* onEndCall: ({ reason, resourceId }) => log.info('agent ended call', { reason, resourceId }),
|
|
40
|
+
* }),
|
|
41
|
+
* // worker
|
|
42
|
+
* createLiveKitWorker({ mastra, agent: 'support', configuration: { endCall: {} } });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createEndCallTool(options?: EndCallToolOptions): import("@mastra/core/tools").Tool<{
|
|
46
|
+
reason?: string | null | undefined;
|
|
47
|
+
}, {
|
|
48
|
+
ended: boolean;
|
|
49
|
+
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, string, unknown>;
|
|
50
|
+
//# sourceMappingURL=end-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"end-call.d.ts","sourceRoot":"","sources":["../src/end-call.ts"],"names":[],"mappings":"AAMA,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAUD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB;;;;oHA0BjE"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_workflow_generator = require("./workflow-generator-B67QrY8L.cjs");
|
|
3
|
+
let crypto = require("crypto");
|
|
4
|
+
let _livekit_protocol = require("@livekit/protocol");
|
|
5
|
+
let livekit_server_sdk = require("livekit-server-sdk");
|
|
6
|
+
let _mastra_core_tools = require("@mastra/core/tools");
|
|
7
|
+
let zod = require("zod");
|
|
8
|
+
//#region src/routes.ts
|
|
9
|
+
function stringField(body, key) {
|
|
10
|
+
const value = body[key];
|
|
11
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* An ApiRoute for `server.apiRoutes` that mints a LiveKit access token with the Mastra
|
|
15
|
+
* voice agent dispatched into the room. Frontends call it to join a voice session:
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* export const mastra = new Mastra({
|
|
19
|
+
* agents: { support },
|
|
20
|
+
* server: { apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })] },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function liveKitConnectionRoute(options = {}) {
|
|
25
|
+
const handler = async (c) => {
|
|
26
|
+
const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;
|
|
27
|
+
const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;
|
|
28
|
+
const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;
|
|
29
|
+
if (!serverUrl || !apiKey || !apiSecret) return c.json({ error: "LiveKit is not configured. Set LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET (or pass serverUrl/apiKey/apiSecret to liveKitConnectionRoute)." }, 500);
|
|
30
|
+
const body = await c.req.json().then((parsed) => parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {}).catch(() => ({}));
|
|
31
|
+
const args = {
|
|
32
|
+
body,
|
|
33
|
+
context: c
|
|
34
|
+
};
|
|
35
|
+
const metadata = options.metadata ? await options.metadata(args) : {
|
|
36
|
+
agentId: stringField(body, "agentId"),
|
|
37
|
+
threadId: stringField(body, "threadId"),
|
|
38
|
+
resourceId: stringField(body, "resourceId")
|
|
39
|
+
};
|
|
40
|
+
const roomName = typeof options.roomName === "function" ? options.roomName(args) : options.roomName ?? `mastra-voice-${(0, crypto.randomUUID)().slice(0, 8)}`;
|
|
41
|
+
const identity = typeof options.participantIdentity === "function" ? options.participantIdentity(args) : options.participantIdentity ?? metadata.resourceId ?? `user-${(0, crypto.randomUUID)().slice(0, 8)}`;
|
|
42
|
+
metadata.threadId ??= roomName;
|
|
43
|
+
const token = new livekit_server_sdk.AccessToken(apiKey, apiSecret, {
|
|
44
|
+
identity,
|
|
45
|
+
ttl: options.ttl ?? "15m"
|
|
46
|
+
});
|
|
47
|
+
token.addGrant({
|
|
48
|
+
room: roomName,
|
|
49
|
+
roomJoin: true,
|
|
50
|
+
canPublish: true,
|
|
51
|
+
canSubscribe: true,
|
|
52
|
+
canPublishData: true,
|
|
53
|
+
canUpdateOwnMetadata: true
|
|
54
|
+
});
|
|
55
|
+
token.roomConfig = new _livekit_protocol.RoomConfiguration({ agents: [new _livekit_protocol.RoomAgentDispatch({
|
|
56
|
+
agentName: options.agentName ?? "mastra-voice",
|
|
57
|
+
metadata: require_workflow_generator.serializeSessionMetadata(metadata)
|
|
58
|
+
})] });
|
|
59
|
+
const details = {
|
|
60
|
+
serverUrl,
|
|
61
|
+
roomName,
|
|
62
|
+
participantName: identity,
|
|
63
|
+
participantToken: await token.toJwt()
|
|
64
|
+
};
|
|
65
|
+
return c.json(details);
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
path: options.path ?? "/voice/livekit/connection-details",
|
|
69
|
+
method: "POST",
|
|
70
|
+
requiresAuth: options.requiresAuth,
|
|
71
|
+
handler
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/dispatch.ts
|
|
76
|
+
function toHttpUrl(url) {
|
|
77
|
+
return url.replace(/^ws/, "http");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Programmatically dispatches a Mastra voice agent into a LiveKit room — for
|
|
81
|
+
* server-initiated sessions such as outbound calls or joining an existing room.
|
|
82
|
+
*/
|
|
83
|
+
async function dispatchVoiceSession(options) {
|
|
84
|
+
const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;
|
|
85
|
+
const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;
|
|
86
|
+
const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;
|
|
87
|
+
if (!serverUrl) throw new Error("@mastra/livekit: set LIVEKIT_URL or pass serverUrl to dispatchVoiceSession.");
|
|
88
|
+
if (!apiKey || !apiSecret) throw new Error("@mastra/livekit: set LIVEKIT_API_KEY and LIVEKIT_API_SECRET or pass apiKey/apiSecret to dispatchVoiceSession.");
|
|
89
|
+
return new livekit_server_sdk.AgentDispatchClient(toHttpUrl(serverUrl), apiKey, apiSecret).createDispatch(options.roomName, options.agentName ?? "mastra-voice", { metadata: require_workflow_generator.serializeSessionMetadata(options.metadata ?? {}) });
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/consent.ts
|
|
93
|
+
const DEFAULT_DESCRIPTION$1 = "Record the caller's consent decision for a data-processing item (for example, storing a summary of the call). Call this as soon as the caller answers a consent question: granted = true if they agree, false if they decline. Do not proceed with an activity that requires consent until you have recorded the caller granting it.";
|
|
94
|
+
/**
|
|
95
|
+
* Builds a Mastra tool that captures the caller's consent decisions at runtime — the companion to
|
|
96
|
+
* the worker's `configuration.consentPolicy`, which only DECLARES which consents a call needs. Add
|
|
97
|
+
* it to the agent that answers the call; on each call the tool reads the caller's `resourceId` /
|
|
98
|
+
* `threadId` from its execution context and hands the decision to your `onGrant` store. The runtime
|
|
99
|
+
* grants live only where `onGrant` put them: enforce consent by reading them back from your own
|
|
100
|
+
* store — at `onCallEnd` or before any consent-gated action — cross-checking against the declared
|
|
101
|
+
* requirements in `VoiceCallEndArgs.configuration.consentPolicy` (the configuration carries the
|
|
102
|
+
* policy, never the grants).
|
|
103
|
+
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* // agent tools
|
|
106
|
+
* recordConsent: createConsentTool({
|
|
107
|
+
* items: ['summaryStorage'],
|
|
108
|
+
* onGrant: async ({ item, granted, resourceId }) => {
|
|
109
|
+
* if (resourceId) await db.saveConsent(resourceId, item, granted);
|
|
110
|
+
* },
|
|
111
|
+
* }),
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
function createConsentTool(options) {
|
|
115
|
+
const items = options.items;
|
|
116
|
+
const itemSchema = items && items.length > 0 ? zod.z.enum([...items]) : zod.z.string();
|
|
117
|
+
return (0, _mastra_core_tools.createTool)({
|
|
118
|
+
id: options.id ?? "recordConsent",
|
|
119
|
+
description: options.description ?? DEFAULT_DESCRIPTION$1,
|
|
120
|
+
inputSchema: zod.z.object({
|
|
121
|
+
item: itemSchema.describe("The consent item the caller is answering for (matches the deployment's required consents)."),
|
|
122
|
+
granted: zod.z.boolean().describe("True if the caller agreed, false if they declined.")
|
|
123
|
+
}),
|
|
124
|
+
execute: async ({ item, granted }, { agent }) => {
|
|
125
|
+
await options.onGrant({
|
|
126
|
+
item,
|
|
127
|
+
granted,
|
|
128
|
+
resourceId: agent?.resourceId,
|
|
129
|
+
threadId: agent?.threadId
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
recorded: true,
|
|
133
|
+
item,
|
|
134
|
+
granted
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/end-call.ts
|
|
141
|
+
const DEFAULT_DESCRIPTION = "End the phone call. Call this only after you have said goodbye and there is nothing left to do — for example the caller says goodbye, or the task is complete and you have wrapped up. Say your closing line first, then call this as your final action; the call hangs up once your words finish playing. Your closing line must be a final statement, never a question — if you are asking the caller anything (for example whether they need anything else), do NOT call this in that reply; wait for their answer. Do not call it if the caller still needs something.";
|
|
142
|
+
/**
|
|
143
|
+
* Builds a Mastra tool the agent calls to end the call itself (say goodbye → hang up). It is the
|
|
144
|
+
* agent-visible half of agent-initiated hang-up: the tool only SIGNALS intent (and runs optional
|
|
145
|
+
* bookkeeping) — it can't reach the LiveKit room from inside `agent.stream()`. The worker owns the
|
|
146
|
+
* hang-up: with `configuration.endCall` set, it watches each turn for this tool, waits for the
|
|
147
|
+
* agent's closing words to finish playing, then disconnects (running `onCallEnd` on the way out).
|
|
148
|
+
* Keeping the tool inside the single agent means it stays visible/editable in Studio and works on
|
|
149
|
+
* the agent and workflow reply paths alike.
|
|
150
|
+
*
|
|
151
|
+
* ```ts
|
|
152
|
+
* // agent tools
|
|
153
|
+
* endCall: createEndCallTool({
|
|
154
|
+
* onEndCall: ({ reason, resourceId }) => log.info('agent ended call', { reason, resourceId }),
|
|
155
|
+
* }),
|
|
156
|
+
* // worker
|
|
157
|
+
* createLiveKitWorker({ mastra, agent: 'support', configuration: { endCall: {} } });
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
function createEndCallTool(options = {}) {
|
|
161
|
+
return (0, _mastra_core_tools.createTool)({
|
|
162
|
+
id: options.id ?? "endCall",
|
|
163
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
164
|
+
inputSchema: zod.z.object({ reason: zod.z.string().nullish().describe("Short reason the call is ending, e.g. \"caller said goodbye\" or \"task complete\".") }),
|
|
165
|
+
outputSchema: zod.z.object({ ended: zod.z.boolean() }),
|
|
166
|
+
execute: async ({ reason }, { agent }) => {
|
|
167
|
+
try {
|
|
168
|
+
await options.onEndCall?.({
|
|
169
|
+
reason: reason ?? void 0,
|
|
170
|
+
resourceId: agent?.resourceId,
|
|
171
|
+
threadId: agent?.threadId
|
|
172
|
+
});
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.warn("@mastra/livekit: onEndCall hook threw", error);
|
|
175
|
+
}
|
|
176
|
+
return { ended: true };
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
exports.DEFAULT_LIVEKIT_AGENT_NAME = require_workflow_generator.DEFAULT_LIVEKIT_AGENT_NAME;
|
|
182
|
+
exports.createConsentTool = createConsentTool;
|
|
183
|
+
exports.createEndCallTool = createEndCallTool;
|
|
184
|
+
exports.dispatchVoiceSession = dispatchVoiceSession;
|
|
185
|
+
exports.liveKitConnectionRoute = liveKitConnectionRoute;
|
|
186
|
+
exports.pipeAgentReplyToWriter = require_workflow_generator.pipeAgentReplyToWriter;
|
|
187
|
+
exports.serializeSessionMetadata = require_workflow_generator.serializeSessionMetadata;
|
|
188
|
+
|
|
189
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["AccessToken","RoomConfiguration","RoomAgentDispatch","serializeSessionMetadata","AgentDispatchClient","serializeSessionMetadata","DEFAULT_DESCRIPTION","z","z"],"sources":["../src/routes.ts","../src/dispatch.ts","../src/consent.ts","../src/end-call.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol';\nimport type { ContextWithMastra, ApiRoute } from '@mastra/core/server';\nimport { AccessToken } from 'livekit-server-sdk';\nimport { DEFAULT_LIVEKIT_AGENT_NAME } from './constants';\nimport { serializeSessionMetadata } from './metadata';\nimport type { LiveKitSessionMetadata } from './metadata';\n\n/** Response body of the connection-details route. Matches LiveKit's frontend starter contract. */\nexport interface LiveKitConnectionDetails {\n serverUrl: string;\n roomName: string;\n participantName: string;\n participantToken: string;\n}\n\nexport interface ConnectionRequestArgs {\n body: Record<string, unknown>;\n context: ContextWithMastra;\n}\n\nexport interface LiveKitConnectionRouteOptions {\n /**\n * Route path. Defaults to `/voice/livekit/connection-details`. Mastra reserves the\n * `/api` prefix for built-in routes, so custom paths must not start with `/api`.\n */\n path?: string;\n /** LiveKit server URL (`wss://...`). Defaults to `LIVEKIT_URL`. */\n serverUrl?: string;\n /** Defaults to `LIVEKIT_API_KEY`. */\n apiKey?: string;\n /** Defaults to `LIVEKIT_API_SECRET`. */\n apiSecret?: string;\n /** LiveKit agent name for explicit dispatch. Must match the worker's `agentName`. */\n agentName?: string;\n /** Token time-to-live. Defaults to `'15m'`. */\n ttl?: string | number;\n /** Defaults to `true` (Mastra custom routes require auth unless opted out). */\n requiresAuth?: boolean;\n roomName?: string | ((args: ConnectionRequestArgs) => string);\n participantIdentity?: string | ((args: ConnectionRequestArgs) => string);\n /**\n * Session metadata delivered to the worker via agent dispatch. Defaults to passing\n * through `agentId`, `threadId`, and `resourceId` from the request body.\n */\n metadata?: (args: ConnectionRequestArgs) => LiveKitSessionMetadata | Promise<LiveKitSessionMetadata>;\n}\n\nfunction stringField(body: Record<string, unknown>, key: string): string | undefined {\n const value = body[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/**\n * An ApiRoute for `server.apiRoutes` that mints a LiveKit access token with the Mastra\n * voice agent dispatched into the room. Frontends call it to join a voice session:\n *\n * ```ts\n * export const mastra = new Mastra({\n * agents: { support },\n * server: { apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })] },\n * });\n * ```\n */\nexport function liveKitConnectionRoute(options: LiveKitConnectionRouteOptions = {}): ApiRoute {\n const handler = async (c: ContextWithMastra) => {\n const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;\n const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;\n const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;\n if (!serverUrl || !apiKey || !apiSecret) {\n return c.json(\n {\n error:\n 'LiveKit is not configured. Set LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET ' +\n '(or pass serverUrl/apiKey/apiSecret to liveKitConnectionRoute).',\n },\n 500,\n );\n }\n\n const body: Record<string, unknown> = await c.req\n .json()\n .then((parsed: unknown) =>\n parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : {},\n )\n .catch(() => ({}));\n const args: ConnectionRequestArgs = { body, context: c };\n\n const metadata: LiveKitSessionMetadata = options.metadata\n ? await options.metadata(args)\n : {\n agentId: stringField(body, 'agentId'),\n threadId: stringField(body, 'threadId'),\n resourceId: stringField(body, 'resourceId'),\n };\n\n const roomName =\n typeof options.roomName === 'function'\n ? options.roomName(args)\n : (options.roomName ?? `mastra-voice-${randomUUID().slice(0, 8)}`);\n const identity =\n typeof options.participantIdentity === 'function'\n ? options.participantIdentity(args)\n : (options.participantIdentity ?? metadata.resourceId ?? `user-${randomUUID().slice(0, 8)}`);\n // One memory thread per room unless the caller pins a thread explicitly.\n metadata.threadId ??= roomName;\n\n const token = new AccessToken(apiKey, apiSecret, { identity, ttl: options.ttl ?? '15m' });\n token.addGrant({\n room: roomName,\n roomJoin: true,\n canPublish: true,\n canSubscribe: true,\n canPublishData: true,\n canUpdateOwnMetadata: true,\n });\n token.roomConfig = new RoomConfiguration({\n agents: [\n new RoomAgentDispatch({\n agentName: options.agentName ?? DEFAULT_LIVEKIT_AGENT_NAME,\n metadata: serializeSessionMetadata(metadata),\n }),\n ],\n });\n\n const details: LiveKitConnectionDetails = {\n serverUrl,\n roomName,\n participantName: identity,\n participantToken: await token.toJwt(),\n };\n return c.json(details);\n };\n\n return {\n path: options.path ?? '/voice/livekit/connection-details',\n method: 'POST',\n requiresAuth: options.requiresAuth,\n handler,\n } as ApiRoute;\n}\n","import { AgentDispatchClient } from 'livekit-server-sdk';\nimport { DEFAULT_LIVEKIT_AGENT_NAME } from './constants';\nimport { serializeSessionMetadata } from './metadata';\nimport type { LiveKitSessionMetadata } from './metadata';\n\nexport interface DispatchVoiceSessionOptions {\n /** Room to dispatch the agent into (created on demand). */\n roomName: string;\n /** Must match the worker's `agentName`. Defaults to `'mastra-voice'`. */\n agentName?: string;\n metadata?: LiveKitSessionMetadata;\n /** Defaults to `LIVEKIT_URL`. */\n serverUrl?: string;\n /** Defaults to `LIVEKIT_API_KEY`. */\n apiKey?: string;\n /** Defaults to `LIVEKIT_API_SECRET`. */\n apiSecret?: string;\n}\n\nfunction toHttpUrl(url: string): string {\n return url.replace(/^ws/, 'http');\n}\n\n/**\n * Programmatically dispatches a Mastra voice agent into a LiveKit room — for\n * server-initiated sessions such as outbound calls or joining an existing room.\n */\nexport async function dispatchVoiceSession(options: DispatchVoiceSessionOptions) {\n const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;\n const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;\n const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;\n if (!serverUrl) {\n throw new Error('@mastra/livekit: set LIVEKIT_URL or pass serverUrl to dispatchVoiceSession.');\n }\n if (!apiKey || !apiSecret) {\n throw new Error(\n '@mastra/livekit: set LIVEKIT_API_KEY and LIVEKIT_API_SECRET or pass apiKey/apiSecret to dispatchVoiceSession.',\n );\n }\n const client = new AgentDispatchClient(toHttpUrl(serverUrl), apiKey, apiSecret);\n return client.createDispatch(options.roomName, options.agentName ?? DEFAULT_LIVEKIT_AGENT_NAME, {\n metadata: serializeSessionMetadata(options.metadata ?? {}),\n });\n}\n","// Server-safe: only depends on `@mastra/core` + zod, never the `@livekit/agents` runtime — so it\n// can be added to agents defined in server/shared code and re-exported from the root entry\n// (`index.ts`). `index.test.ts` enforces that boundary.\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\n/** A consent decision captured from the caller during a call. */\nexport interface ConsentGrant {\n /**\n * The consent item, matching a key in the worker's `configuration.consentPolicy` (e.g.\n * `'summaryStorage'`).\n */\n item: string;\n /** `true` if the caller agreed, `false` if they declined. */\n granted: boolean;\n /** The caller the grant belongs to (the memory `resource`), when the call is memory-scoped. */\n resourceId?: string;\n /** The call thread the grant was captured on, when the call is memory-scoped. */\n threadId?: string;\n}\n\nexport interface ConsentToolOptions {\n /**\n * Persist the caller's decision to YOUR system of record (database, CRM, consent ledger). Called\n * each time the caller answers a consent question — keep it quick, it runs inside the turn. This\n * tool owns extracting the caller's identity from the tool execution context; you own storage, so\n * consent lives in a durable, compliant place rather than an opaque plugin store. Read those\n * grants back at `onCallEnd` (or before any consent-gated step) to enforce the requirement.\n */\n onGrant: (grant: ConsentGrant) => void | Promise<void>;\n /** Tool id the agent calls. Defaults to `'recordConsent'`. */\n id?: string;\n /** Override the description the model sees when deciding to call the tool. */\n description?: string;\n /** Restrict the accepted consent items to this set (becomes an enum). Defaults to any string. */\n items?: readonly string[];\n}\n\nconst DEFAULT_DESCRIPTION =\n \"Record the caller's consent decision for a data-processing item (for example, storing a summary \" +\n 'of the call). Call this as soon as the caller answers a consent question: granted = true if they ' +\n 'agree, false if they decline. Do not proceed with an activity that requires consent until you ' +\n 'have recorded the caller granting it.';\n\n/**\n * Builds a Mastra tool that captures the caller's consent decisions at runtime — the companion to\n * the worker's `configuration.consentPolicy`, which only DECLARES which consents a call needs. Add\n * it to the agent that answers the call; on each call the tool reads the caller's `resourceId` /\n * `threadId` from its execution context and hands the decision to your `onGrant` store. The runtime\n * grants live only where `onGrant` put them: enforce consent by reading them back from your own\n * store — at `onCallEnd` or before any consent-gated action — cross-checking against the declared\n * requirements in `VoiceCallEndArgs.configuration.consentPolicy` (the configuration carries the\n * policy, never the grants).\n *\n * ```ts\n * // agent tools\n * recordConsent: createConsentTool({\n * items: ['summaryStorage'],\n * onGrant: async ({ item, granted, resourceId }) => {\n * if (resourceId) await db.saveConsent(resourceId, item, granted);\n * },\n * }),\n * ```\n */\nexport function createConsentTool(options: ConsentToolOptions) {\n const items = options.items;\n const itemSchema = items && items.length > 0 ? z.enum([...items] as [string, ...string[]]) : z.string();\n return createTool({\n id: options.id ?? 'recordConsent',\n description: options.description ?? DEFAULT_DESCRIPTION,\n inputSchema: z.object({\n item: itemSchema.describe(\n \"The consent item the caller is answering for (matches the deployment's required consents).\",\n ),\n granted: z.boolean().describe('True if the caller agreed, false if they declined.'),\n }),\n execute: async ({ item, granted }, { agent }) => {\n await options.onGrant({ item, granted, resourceId: agent?.resourceId, threadId: agent?.threadId });\n return { recorded: true as const, item, granted };\n },\n });\n}\n","// Server-safe: only depends on `@mastra/core` + zod, never the `@livekit/agents` runtime — so it\n// can be added to agents defined in server/shared code and re-exported from the root entry\n// (`index.ts`). `index.test.ts` enforces that boundary.\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\n/** Details of the agent's decision to end the call, handed to {@link EndCallToolOptions.onEndCall}. */\nexport interface EndCallRequest {\n /** Short reason the agent gave for ending the call, if any (e.g. \"caller said goodbye\"). */\n reason?: string;\n /** The caller the call belongs to (the memory `resource`), when the call is memory-scoped. */\n resourceId?: string;\n /** The call thread, when the call is memory-scoped. */\n threadId?: string;\n}\n\nexport interface EndCallToolOptions {\n /**\n * Tool id the agent calls to end the call. Must match the worker's\n * `configuration.endCall.tool` (both default to `'endCall'`), since that's the name the worker\n * watches for to hang up.\n */\n id?: string;\n /** Override the description the model sees when deciding to call the tool. */\n description?: string;\n /**\n * Optional bookkeeping hook, called when the agent invokes the tool (records the reason, marks\n * the call resolved in your CRM, …). Runs inside the turn — keep it quick. It does NOT hang up\n * the call; the worker does that once the agent's final words finish playing. The tool reads the\n * caller's identity from its execution context and passes it here.\n */\n onEndCall?: (request: EndCallRequest) => void | Promise<void>;\n}\n\nconst DEFAULT_DESCRIPTION =\n 'End the phone call. Call this only after you have said goodbye and there is nothing left to do — ' +\n 'for example the caller says goodbye, or the task is complete and you have wrapped up. Say your ' +\n 'closing line first, then call this as your final action; the call hangs up once your words finish ' +\n 'playing. Your closing line must be a final statement, never a question — if you are asking the ' +\n 'caller anything (for example whether they need anything else), do NOT call this in that reply; ' +\n 'wait for their answer. Do not call it if the caller still needs something.';\n\n/**\n * Builds a Mastra tool the agent calls to end the call itself (say goodbye → hang up). It is the\n * agent-visible half of agent-initiated hang-up: the tool only SIGNALS intent (and runs optional\n * bookkeeping) — it can't reach the LiveKit room from inside `agent.stream()`. The worker owns the\n * hang-up: with `configuration.endCall` set, it watches each turn for this tool, waits for the\n * agent's closing words to finish playing, then disconnects (running `onCallEnd` on the way out).\n * Keeping the tool inside the single agent means it stays visible/editable in Studio and works on\n * the agent and workflow reply paths alike.\n *\n * ```ts\n * // agent tools\n * endCall: createEndCallTool({\n * onEndCall: ({ reason, resourceId }) => log.info('agent ended call', { reason, resourceId }),\n * }),\n * // worker\n * createLiveKitWorker({ mastra, agent: 'support', configuration: { endCall: {} } });\n * ```\n */\nexport function createEndCallTool(options: EndCallToolOptions = {}) {\n return createTool({\n id: options.id ?? 'endCall',\n description: options.description ?? DEFAULT_DESCRIPTION,\n inputSchema: z.object({\n reason: z\n .string()\n .nullish()\n .describe('Short reason the call is ending, e.g. \"caller said goodbye\" or \"task complete\".'),\n }),\n outputSchema: z.object({ ended: z.boolean() }),\n execute: async ({ reason }, { agent }) => {\n try {\n await options.onEndCall?.({\n reason: reason ?? undefined,\n resourceId: agent?.resourceId,\n threadId: agent?.threadId,\n });\n } catch (error) {\n // Bookkeeping is best-effort — the tool must still signal `{ ended: true }` so the worker's\n // end-call detector runs and the call actually hangs up.\n console.warn('@mastra/livekit: onEndCall hook threw', error);\n }\n return { ended: true as const };\n },\n });\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { liveKitConnectionRoute } from './routes.js';
|
|
2
|
+
export type { LiveKitConnectionRouteOptions, LiveKitConnectionDetails, ConnectionRequestArgs } from './routes.js';
|
|
3
|
+
export { dispatchVoiceSession } from './dispatch.js';
|
|
4
|
+
export type { DispatchVoiceSessionOptions } from './dispatch.js';
|
|
5
|
+
export { serializeSessionMetadata } from './metadata.js';
|
|
6
|
+
export type { LiveKitSessionMetadata } from './metadata.js';
|
|
7
|
+
export { pipeAgentReplyToWriter } from './workflow-generator.js';
|
|
8
|
+
export type { AgentReplyStreamLike } from './workflow-generator.js';
|
|
9
|
+
export { createConsentTool } from './consent.js';
|
|
10
|
+
export type { ConsentGrant, ConsentToolOptions } from './consent.js';
|
|
11
|
+
export { createEndCallTool } from './end-call.js';
|
|
12
|
+
export type { EndCallRequest, EndCallToolOptions } from './end-call.js';
|
|
13
|
+
export { DEFAULT_LIVEKIT_AGENT_NAME } from './constants.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAC/G,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC"}
|