@voicelayer/sdk 0.1.11 → 0.3.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/README.md +8 -0
- package/dist/brain/index.d.ts +283 -0
- package/dist/brain/index.js +3550 -0
- package/dist/index.d.ts +1472 -1588
- package/dist/index.js +9129 -6719
- package/dist/runtime/text-session.d.ts +2 -1
- package/dist/runtime/text-session.js +1969 -98
- package/dist/{text-session-D1j8nQac.d.ts → text-session-B7oyrhwQ.d.ts} +403 -308
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -328,6 +328,14 @@ export DEEPGRAM_API_KEY=...
|
|
|
328
328
|
node agent.ts start
|
|
329
329
|
```
|
|
330
330
|
|
|
331
|
+
### Texts
|
|
332
|
+
|
|
333
|
+
The same worker answers texts — SMS replies, Discord, your website's chat widget, the dashboard playground. `.start()`
|
|
334
|
+
registers a second LiveKit name, `<name>::text`, beside the voice one; each message is dispatched to it and runs as
|
|
335
|
+
your agent: its tools, security, connectors and model, with the conversation so far. Over text `ctx.call.callerId` is
|
|
336
|
+
the sender, `ctx.call.metadata.mode` is `'text'`, and call-only methods (`handoff`, `endCall`, `ask`, DTMF) throw. In
|
|
337
|
+
production the text registration's health server listens on `VL_TEXT_TURN_PORT` (default 8082).
|
|
338
|
+
|
|
331
339
|
---
|
|
332
340
|
|
|
333
341
|
## What's *not* in this SDK
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { Redis } from 'ioredis';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
/** Frames a daemon sends up to the relay. */
|
|
5
|
+
declare const ConnectorUpFrame: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
6
|
+
kind: z.ZodLiteral<"hello">;
|
|
7
|
+
token: z.ZodString;
|
|
8
|
+
replicaId: z.ZodString;
|
|
9
|
+
version: z.ZodString;
|
|
10
|
+
caps: z.ZodObject<{
|
|
11
|
+
streaming: z.ZodBoolean;
|
|
12
|
+
tools: z.ZodBoolean;
|
|
13
|
+
litellm: z.ZodBoolean;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
tools: boolean;
|
|
16
|
+
streaming: boolean;
|
|
17
|
+
litellm: boolean;
|
|
18
|
+
}, {
|
|
19
|
+
tools: boolean;
|
|
20
|
+
streaming: boolean;
|
|
21
|
+
litellm: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
kind: "hello";
|
|
25
|
+
version: string;
|
|
26
|
+
token: string;
|
|
27
|
+
replicaId: string;
|
|
28
|
+
caps: {
|
|
29
|
+
tools: boolean;
|
|
30
|
+
streaming: boolean;
|
|
31
|
+
litellm: boolean;
|
|
32
|
+
};
|
|
33
|
+
}, {
|
|
34
|
+
kind: "hello";
|
|
35
|
+
version: string;
|
|
36
|
+
token: string;
|
|
37
|
+
replicaId: string;
|
|
38
|
+
caps: {
|
|
39
|
+
tools: boolean;
|
|
40
|
+
streaming: boolean;
|
|
41
|
+
litellm: boolean;
|
|
42
|
+
};
|
|
43
|
+
}>, z.ZodObject<{
|
|
44
|
+
kind: z.ZodLiteral<"pong">;
|
|
45
|
+
ts: z.ZodNumber;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
kind: "pong";
|
|
48
|
+
ts: number;
|
|
49
|
+
}, {
|
|
50
|
+
kind: "pong";
|
|
51
|
+
ts: number;
|
|
52
|
+
}>, z.ZodObject<{
|
|
53
|
+
kind: z.ZodLiteral<"brain.delta">;
|
|
54
|
+
streamId: z.ZodString;
|
|
55
|
+
content: z.ZodString;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
kind: "brain.delta";
|
|
58
|
+
content: string;
|
|
59
|
+
streamId: string;
|
|
60
|
+
}, {
|
|
61
|
+
kind: "brain.delta";
|
|
62
|
+
content: string;
|
|
63
|
+
streamId: string;
|
|
64
|
+
}>, z.ZodObject<{
|
|
65
|
+
kind: z.ZodLiteral<"brain.done">;
|
|
66
|
+
streamId: z.ZodString;
|
|
67
|
+
finishReason: z.ZodString;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
kind: "brain.done";
|
|
70
|
+
streamId: string;
|
|
71
|
+
finishReason: string;
|
|
72
|
+
}, {
|
|
73
|
+
kind: "brain.done";
|
|
74
|
+
streamId: string;
|
|
75
|
+
finishReason: string;
|
|
76
|
+
}>, z.ZodObject<{
|
|
77
|
+
kind: z.ZodLiteral<"brain.error">;
|
|
78
|
+
streamId: z.ZodString;
|
|
79
|
+
code: z.ZodEnum<["upstream_timeout", "upstream_error", "bad_response", "normalize_failed", "unreachable"]>;
|
|
80
|
+
message: z.ZodString;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
code: "upstream_timeout" | "upstream_error" | "bad_response" | "normalize_failed" | "unreachable";
|
|
83
|
+
message: string;
|
|
84
|
+
kind: "brain.error";
|
|
85
|
+
streamId: string;
|
|
86
|
+
}, {
|
|
87
|
+
code: "upstream_timeout" | "upstream_error" | "bad_response" | "normalize_failed" | "unreachable";
|
|
88
|
+
message: string;
|
|
89
|
+
kind: "brain.error";
|
|
90
|
+
streamId: string;
|
|
91
|
+
}>]>;
|
|
92
|
+
type ConnectorUpFrame = z.infer<typeof ConnectorUpFrame>;
|
|
93
|
+
|
|
94
|
+
interface BrainMessage {
|
|
95
|
+
readonly role: 'system' | 'user' | 'assistant';
|
|
96
|
+
readonly content: string;
|
|
97
|
+
}
|
|
98
|
+
interface BrainCallMetadata {
|
|
99
|
+
readonly channel: 'voice' | 'text';
|
|
100
|
+
readonly callId?: string;
|
|
101
|
+
readonly projectId?: string;
|
|
102
|
+
}
|
|
103
|
+
interface BrainRequest {
|
|
104
|
+
readonly messages: readonly BrainMessage[];
|
|
105
|
+
/** Upstream model id / alias. Omitted → the brain's own default. */
|
|
106
|
+
readonly model?: string;
|
|
107
|
+
readonly temperature?: number;
|
|
108
|
+
readonly metadata: BrainCallMetadata;
|
|
109
|
+
}
|
|
110
|
+
/** One streamed piece of the brain's reply. */
|
|
111
|
+
interface BrainChunk {
|
|
112
|
+
readonly content?: string;
|
|
113
|
+
}
|
|
114
|
+
interface BrainCapabilities {
|
|
115
|
+
readonly reachable: boolean;
|
|
116
|
+
readonly streaming: boolean;
|
|
117
|
+
}
|
|
118
|
+
interface BrainTransport {
|
|
119
|
+
readonly kind: 'callback' | 'http' | 'tunnel';
|
|
120
|
+
/** Stream the reply token-by-token (the voice path: first sentence → TTS ASAP). */
|
|
121
|
+
stream(req: BrainRequest, signal: AbortSignal): AsyncIterable<BrainChunk>;
|
|
122
|
+
/** Non-streaming convenience (the text path). */
|
|
123
|
+
complete(req: BrainRequest, signal: AbortSignal): Promise<string>;
|
|
124
|
+
}
|
|
125
|
+
/** Context handed to a customer's in-process `onQuery` brain. */
|
|
126
|
+
interface OnQueryContext {
|
|
127
|
+
/** Full conversation so far (system + prior turns + latest user message). */
|
|
128
|
+
readonly messages: readonly BrainMessage[];
|
|
129
|
+
/** Aborts when the caller barges in / the turn is cancelled. */
|
|
130
|
+
readonly signal: AbortSignal;
|
|
131
|
+
}
|
|
132
|
+
type OnQueryResult = string | AsyncIterable<string>;
|
|
133
|
+
/**
|
|
134
|
+
* Bring-your-own brain, in-process. Receives the latest user utterance (and the
|
|
135
|
+
* full history via `ctx.messages`) and returns the reply — either a string or an
|
|
136
|
+
* async-iterable of string pieces for token streaming.
|
|
137
|
+
*/
|
|
138
|
+
type OnQuery = (text: string, ctx: OnQueryContext) => OnQueryResult | Promise<OnQueryResult>;
|
|
139
|
+
|
|
140
|
+
declare function callbackTransport(onQuery: OnQuery): BrainTransport;
|
|
141
|
+
|
|
142
|
+
/** Convert a LK ChatContext (or any `{items}` shape) into BrainMessages. */
|
|
143
|
+
declare function chatContextToMessages(chatCtx: unknown): BrainMessage[];
|
|
144
|
+
/** The most recent user utterance, or '' if none. */
|
|
145
|
+
declare function lastUserText(messages: readonly BrainMessage[]): string;
|
|
146
|
+
|
|
147
|
+
interface ConnectorLLMOptions {
|
|
148
|
+
readonly model?: string;
|
|
149
|
+
readonly temperature?: number;
|
|
150
|
+
readonly callId?: string;
|
|
151
|
+
readonly projectId?: string;
|
|
152
|
+
/** Spoken instead of dead air when the brain errors before any reply. */
|
|
153
|
+
readonly fallbackText?: string;
|
|
154
|
+
}
|
|
155
|
+
/** One ChatChunk in the shape AgentSession consumes (subset of LK's ChatChunk). */
|
|
156
|
+
interface ConnectorChatChunk {
|
|
157
|
+
readonly id: string;
|
|
158
|
+
readonly delta: {
|
|
159
|
+
readonly role: 'assistant';
|
|
160
|
+
readonly content: string;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Stream a brain reply as ChatChunks. On error before any content is emitted,
|
|
165
|
+
* falls back to `fallbackText` if provided; otherwise rethrows. Errors after
|
|
166
|
+
* partial output stop the stream (the partial is already spoken).
|
|
167
|
+
*/
|
|
168
|
+
declare function chatChunkStream(transport: BrainTransport, messages: ReturnType<typeof chatContextToMessages>, options: ConnectorLLMOptions, signal: AbortSignal): AsyncGenerator<ConnectorChatChunk>;
|
|
169
|
+
/**
|
|
170
|
+
* Build a ConnectorLLM instance for the pipeline's `llm` slot. The returned
|
|
171
|
+
* object's chat() yields the brain reply and exposes close() for barge-in.
|
|
172
|
+
*/
|
|
173
|
+
declare function createConnectorLLM(transport: BrainTransport, options?: ConnectorLLMOptions): Promise<unknown>;
|
|
174
|
+
|
|
175
|
+
interface ConnectorChatModelOptions {
|
|
176
|
+
readonly model?: string;
|
|
177
|
+
}
|
|
178
|
+
interface ChatModelInput {
|
|
179
|
+
readonly messages: readonly {
|
|
180
|
+
readonly role: 'system' | 'user' | 'assistant';
|
|
181
|
+
readonly content: string;
|
|
182
|
+
}[];
|
|
183
|
+
readonly json?: boolean;
|
|
184
|
+
readonly temperature?: number;
|
|
185
|
+
readonly model?: string;
|
|
186
|
+
}
|
|
187
|
+
declare class ConnectorChatModel {
|
|
188
|
+
private readonly transport;
|
|
189
|
+
private readonly options;
|
|
190
|
+
constructor(transport: BrainTransport, options?: ConnectorChatModelOptions);
|
|
191
|
+
/** `signal` cancels the brain request (the tunnel sends `brain.cancel`); a deadline is the caller's to set. */
|
|
192
|
+
complete(input: ChatModelInput, signal?: AbortSignal): Promise<string>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
declare class BrainConfigError extends Error {
|
|
196
|
+
constructor(message: string);
|
|
197
|
+
}
|
|
198
|
+
/** Resolve a hostname to a list of IP strings. Injectable for tests. */
|
|
199
|
+
type HostLookup = (host: string) => Promise<readonly string[]>;
|
|
200
|
+
interface AssertUrlOptions {
|
|
201
|
+
/** Hostnames that bypass IP checks (explicit per-connector allowlist). */
|
|
202
|
+
readonly allowHosts?: readonly string[];
|
|
203
|
+
/** Override DNS resolution (tests). */
|
|
204
|
+
readonly lookup?: HostLookup;
|
|
205
|
+
}
|
|
206
|
+
/** True if `ip` is a literal address we must refuse. */
|
|
207
|
+
declare function isDisallowedIp(ip: string): boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Validate a brain URL for direct egress. Throws BrainConfigError on any
|
|
210
|
+
* violation; returns the parsed URL when safe.
|
|
211
|
+
*/
|
|
212
|
+
declare function assertPublicHttpsUrl(raw: string, opts?: AssertUrlOptions): Promise<URL>;
|
|
213
|
+
|
|
214
|
+
interface HttpBrainTransportOptions {
|
|
215
|
+
readonly baseUrl: string;
|
|
216
|
+
readonly apiKey?: string;
|
|
217
|
+
readonly defaultModel?: string;
|
|
218
|
+
/** Hostnames that bypass the IP checks (tests, an allow-listed private brain). */
|
|
219
|
+
readonly allowHosts?: readonly string[];
|
|
220
|
+
/** Test seams. */
|
|
221
|
+
readonly fetchImpl?: typeof fetch;
|
|
222
|
+
readonly lookup?: HostLookup;
|
|
223
|
+
}
|
|
224
|
+
declare function httpBrainTransport(opts: HttpBrainTransportOptions): BrainTransport;
|
|
225
|
+
|
|
226
|
+
declare class BrainRequestError extends Error {
|
|
227
|
+
readonly code: string;
|
|
228
|
+
constructor(code: string, message: string);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
interface BrainPubSub {
|
|
232
|
+
publish(channel: string, message: string): Promise<void>;
|
|
233
|
+
/** Subscribe to a channel; returns an unsubscribe handle. */
|
|
234
|
+
subscribe(channel: string, handler: (raw: string) => void): Promise<() => Promise<void>>;
|
|
235
|
+
}
|
|
236
|
+
interface TunnelBrainTransportOptions {
|
|
237
|
+
readonly connectorId: string;
|
|
238
|
+
readonly pubsub: BrainPubSub;
|
|
239
|
+
/** Fail the turn if the daemon sends nothing within this window. Default 20s. */
|
|
240
|
+
readonly firstChunkTimeoutMs?: number;
|
|
241
|
+
}
|
|
242
|
+
declare function tunnelBrainTransport(options: TunnelBrainTransportOptions): BrainTransport;
|
|
243
|
+
|
|
244
|
+
declare class RedisBrainPubSub implements BrainPubSub {
|
|
245
|
+
private readonly sub;
|
|
246
|
+
private readonly pub;
|
|
247
|
+
private readonly listeners;
|
|
248
|
+
constructor(sub: Redis, pub: Redis);
|
|
249
|
+
publish(channel: string, message: string): Promise<void>;
|
|
250
|
+
subscribe(channel: string, handler: (raw: string) => void): Promise<() => Promise<void>>;
|
|
251
|
+
close(): Promise<void>;
|
|
252
|
+
}
|
|
253
|
+
declare function buildRedisBrainPubSub(redisUrl: string | undefined): RedisBrainPubSub | null;
|
|
254
|
+
|
|
255
|
+
interface SseDelta {
|
|
256
|
+
readonly content?: string;
|
|
257
|
+
readonly finishReason?: string;
|
|
258
|
+
}
|
|
259
|
+
declare function parseChatCompletionSse(source: AsyncIterable<Uint8Array> | ReadableStream<Uint8Array>): AsyncGenerator<SseDelta>;
|
|
260
|
+
|
|
261
|
+
interface BrainEndpointConfig {
|
|
262
|
+
/** Base URL of the OpenAI-compatible endpoint, e.g. http://localhost:4000/v1. */
|
|
263
|
+
readonly brainUrl: string;
|
|
264
|
+
readonly apiKey?: string;
|
|
265
|
+
readonly defaultModel?: string;
|
|
266
|
+
/** Injectable for tests; defaults to global fetch. */
|
|
267
|
+
readonly fetchImpl?: typeof fetch;
|
|
268
|
+
/** Refuse redirects (direct egress from VoiceLayer's own servers — the SSRF rule). Default: follow (the daemon). */
|
|
269
|
+
readonly refuseRedirects?: boolean;
|
|
270
|
+
}
|
|
271
|
+
interface IncomingBrainRequest {
|
|
272
|
+
readonly streamId: string;
|
|
273
|
+
readonly model?: string;
|
|
274
|
+
readonly temperature?: number;
|
|
275
|
+
readonly messages: ReadonlyArray<{
|
|
276
|
+
role: 'system' | 'user' | 'assistant';
|
|
277
|
+
content: string;
|
|
278
|
+
}>;
|
|
279
|
+
}
|
|
280
|
+
/** Run one brain.request and yield the reply frames. Never throws. */
|
|
281
|
+
declare function runBrainRequest(req: IncomingBrainRequest, cfg: BrainEndpointConfig, signal: AbortSignal): AsyncGenerator<ConnectorUpFrame>;
|
|
282
|
+
|
|
283
|
+
export { type AssertUrlOptions, type BrainCallMetadata, type BrainCapabilities, type BrainChunk, BrainConfigError, type BrainEndpointConfig, type BrainMessage, type BrainPubSub, type BrainRequest, BrainRequestError, type BrainTransport, type ConnectorChatChunk, ConnectorChatModel, type ConnectorChatModelOptions, type ConnectorLLMOptions, type HostLookup, type HttpBrainTransportOptions, type IncomingBrainRequest, type OnQuery, type OnQueryContext, type OnQueryResult, RedisBrainPubSub, type SseDelta, type TunnelBrainTransportOptions, assertPublicHttpsUrl, buildRedisBrainPubSub, callbackTransport, chatChunkStream, chatContextToMessages, createConnectorLLM, httpBrainTransport, isDisallowedIp, lastUserText, parseChatCompletionSse, runBrainRequest, tunnelBrainTransport };
|