@guava-ai/guava-sdk 0.33.0 → 0.35.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/bin/example-runner.ts +4 -0
- package/dist/bin/example-runner.js +4 -0
- package/dist/bin/example-runner.js.map +1 -1
- package/dist/examples/slow-speech.d.ts +3 -0
- package/dist/examples/slow-speech.js +94 -0
- package/dist/examples/slow-speech.js.map +1 -0
- package/dist/src/action-item.d.ts +4 -4
- package/dist/src/action-item.js +1 -0
- package/dist/src/action-item.js.map +1 -1
- package/dist/src/agent.d.ts +9 -2
- package/dist/src/agent.js +29 -9
- package/dist/src/agent.js.map +1 -1
- package/dist/src/call.d.ts +2 -1
- package/dist/src/call.js +1 -0
- package/dist/src/call.js.map +1 -1
- package/dist/src/commands.d.ts +39 -3
- package/dist/src/commands.js +13 -1
- package/dist/src/commands.js.map +1 -1
- package/dist/src/events.d.ts +84 -3
- package/dist/src/events.js +12 -1
- package/dist/src/events.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/examples/README.md +1 -0
- package/examples/slow-speech.ts +65 -0
- package/package.json +1 -1
- package/src/action-item.ts +1 -0
- package/src/agent.ts +38 -9
- package/src/call.ts +3 -0
- package/src/commands.ts +16 -0
- package/src/events.ts +13 -0
- package/src/index.ts +2 -0
- package/src/version.ts +1 -1
package/src/agent.ts
CHANGED
|
@@ -6,8 +6,11 @@ import {
|
|
|
6
6
|
type Command,
|
|
7
7
|
ExpertErrorCommand,
|
|
8
8
|
RegisteredHooksCommand,
|
|
9
|
+
type SpeedPreset,
|
|
10
|
+
validateSpeedPreset,
|
|
9
11
|
} from "./commands.ts";
|
|
10
12
|
import {
|
|
13
|
+
type AgentDTMFSentEvent,
|
|
11
14
|
type AgentSpeechEvent,
|
|
12
15
|
type BotSessionEnded,
|
|
13
16
|
type CallerSpeechEvent,
|
|
@@ -63,6 +66,7 @@ export class Agent {
|
|
|
63
66
|
private _purpose?: string;
|
|
64
67
|
private _voice?: string;
|
|
65
68
|
private _ttsReplacements?: Record<string, string>;
|
|
69
|
+
private _speechSpeed?: SpeedPreset;
|
|
66
70
|
private _acceptDtmfForNumbers: boolean;
|
|
67
71
|
private _logger: Logger;
|
|
68
72
|
|
|
@@ -93,7 +97,8 @@ export class Agent {
|
|
|
93
97
|
> = {};
|
|
94
98
|
private _onSessionEnd?: (call: Call, event: BotSessionEnded) => Promise<void>;
|
|
95
99
|
private _onEscalate?: (call: Call, event: EscalateEvent) => Promise<void>;
|
|
96
|
-
private
|
|
100
|
+
private _onCallerDtmf?: (call: Call, event: DTMFPressedEvent) => Promise<void>;
|
|
101
|
+
private _onAgentDtmf?: (call: Call, event: AgentDTMFSentEvent) => Promise<void>;
|
|
97
102
|
private _onOutboundFailed?: (call: Call, event: OutboundCallFailed) => Promise<void>;
|
|
98
103
|
|
|
99
104
|
constructor(args?: {
|
|
@@ -103,6 +108,7 @@ export class Agent {
|
|
|
103
108
|
voice?: string;
|
|
104
109
|
pronunciations?: Record<string, string>;
|
|
105
110
|
acceptDtmf?: boolean;
|
|
111
|
+
speechSpeed?: SpeedPreset;
|
|
106
112
|
}) {
|
|
107
113
|
this._name = args?.name;
|
|
108
114
|
this._organization = args?.organization;
|
|
@@ -110,6 +116,8 @@ export class Agent {
|
|
|
110
116
|
this._voice = args?.voice;
|
|
111
117
|
this._ttsReplacements = args?.pronunciations;
|
|
112
118
|
this._acceptDtmfForNumbers = args?.acceptDtmf ?? true;
|
|
119
|
+
validateSpeedPreset(args?.speechSpeed); // Validate the preset name early, at construction.
|
|
120
|
+
this._speechSpeed = args?.speechSpeed;
|
|
113
121
|
this._logger = getDefaultLogger();
|
|
114
122
|
}
|
|
115
123
|
|
|
@@ -196,8 +204,17 @@ export class Agent {
|
|
|
196
204
|
this._onEscalate = callback;
|
|
197
205
|
}
|
|
198
206
|
|
|
207
|
+
onCallerDtmf(callback: (call: Call, event: DTMFPressedEvent) => Promise<void>): void {
|
|
208
|
+
this._onCallerDtmf = callback;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Alias for {@link onCallerDtmf}; will be marked deprecated in a future release. */
|
|
199
212
|
onDtmf(callback: (call: Call, event: DTMFPressedEvent) => Promise<void>): void {
|
|
200
|
-
this.
|
|
213
|
+
this._onCallerDtmf = callback;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
onAgentDtmf(callback: (call: Call, event: AgentDTMFSentEvent) => Promise<void>): void {
|
|
217
|
+
this._onAgentDtmf = callback;
|
|
201
218
|
}
|
|
202
219
|
|
|
203
220
|
onOutboundFailed(callback: (call: Call, event: OutboundCallFailed) => Promise<void>): void {
|
|
@@ -260,7 +277,7 @@ export class Agent {
|
|
|
260
277
|
async listenPhone(phoneNumber: string): Promise<void> {
|
|
261
278
|
const healthCtx = new HealthContext();
|
|
262
279
|
await using _server = await getHealthServer(healthCtx);
|
|
263
|
-
return this._listenInbound(healthCtx, { agent_number: phoneNumber });
|
|
280
|
+
return await this._listenInbound(healthCtx, { agent_number: phoneNumber });
|
|
264
281
|
}
|
|
265
282
|
|
|
266
283
|
async listenWebrtc(webrtcCode?: string): Promise<void> {
|
|
@@ -270,13 +287,13 @@ export class Agent {
|
|
|
270
287
|
}
|
|
271
288
|
const healthCtx = new HealthContext();
|
|
272
289
|
await using _server = await getHealthServer(healthCtx);
|
|
273
|
-
return this._listenInbound(healthCtx, { webrtc_code: webrtcCode });
|
|
290
|
+
return await this._listenInbound(healthCtx, { webrtc_code: webrtcCode });
|
|
274
291
|
}
|
|
275
292
|
|
|
276
293
|
async listenSip(sipCode: string): Promise<void> {
|
|
277
294
|
const healthCtx = new HealthContext();
|
|
278
295
|
await using _server = await getHealthServer(healthCtx);
|
|
279
|
-
return this._listenInbound(healthCtx, { sip_code: sipCode });
|
|
296
|
+
return await this._listenInbound(healthCtx, { sip_code: sipCode });
|
|
280
297
|
}
|
|
281
298
|
|
|
282
299
|
async callLocal(variables: Record<string, any> = {}): Promise<void> {
|
|
@@ -483,8 +500,16 @@ export class Agent {
|
|
|
483
500
|
);
|
|
484
501
|
}
|
|
485
502
|
} else if (event.event_type === "dtmf") {
|
|
486
|
-
if (this.
|
|
487
|
-
await this._invokeHandler(call, "
|
|
503
|
+
if (this._onCallerDtmf !== undefined) {
|
|
504
|
+
await this._invokeHandler(call, "onCallerDtmf", false, () =>
|
|
505
|
+
this._onCallerDtmf!(call, event),
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
} else if (event.event_type === "agent-dtmf") {
|
|
509
|
+
if (this._onAgentDtmf !== undefined) {
|
|
510
|
+
await this._invokeHandler(call, "onAgentDtmf", false, () =>
|
|
511
|
+
this._onAgentDtmf!(call, event),
|
|
512
|
+
);
|
|
488
513
|
}
|
|
489
514
|
} else if (event.event_type === "escalate") {
|
|
490
515
|
if (this._onEscalate !== undefined) {
|
|
@@ -523,6 +548,7 @@ export class Agent {
|
|
|
523
548
|
agentPurpose: this._purpose,
|
|
524
549
|
organizationName: this._organization,
|
|
525
550
|
voice: this._voice,
|
|
551
|
+
speechSpeed: this._speechSpeed,
|
|
526
552
|
pronunciations: this._ttsReplacements,
|
|
527
553
|
});
|
|
528
554
|
await call.sendCommand(RegisteredHooksCommand, {
|
|
@@ -532,6 +558,7 @@ export class Agent {
|
|
|
532
558
|
has_on_action_requested: this._onActionRequested !== undefined,
|
|
533
559
|
has_on_escalate: this._onEscalate !== undefined,
|
|
534
560
|
accept_dtmf_for_numbers: this._acceptDtmfForNumbers,
|
|
561
|
+
has_on_agent_dtmf: this._onAgentDtmf !== undefined,
|
|
535
562
|
});
|
|
536
563
|
if (this._onCallStart !== undefined) {
|
|
537
564
|
await this._onCallStart(call);
|
|
@@ -897,6 +924,7 @@ Choose "speak" and provide your next utterance, or choose "hangup" if the conver
|
|
|
897
924
|
voice: this._voice,
|
|
898
925
|
pronunciations: this._ttsReplacements,
|
|
899
926
|
acceptDtmf: this._acceptDtmfForNumbers,
|
|
927
|
+
speechSpeed: this._speechSpeed,
|
|
900
928
|
});
|
|
901
929
|
cloned._onCallReceived = this._onCallReceived;
|
|
902
930
|
cloned._onCallStart = this._onCallStart;
|
|
@@ -912,7 +940,8 @@ Choose "speak" and provide your next utterance, or choose "hangup" if the conver
|
|
|
912
940
|
cloned._onActionHandlers = { ...this._onActionHandlers };
|
|
913
941
|
cloned._onSessionEnd = this._onSessionEnd;
|
|
914
942
|
cloned._onEscalate = this._onEscalate;
|
|
915
|
-
cloned.
|
|
943
|
+
cloned._onCallerDtmf = this._onCallerDtmf;
|
|
944
|
+
cloned._onAgentDtmf = this._onAgentDtmf;
|
|
916
945
|
cloned._onOutboundFailed = this._onOutboundFailed;
|
|
917
946
|
return cloned;
|
|
918
947
|
}
|
|
@@ -1009,7 +1038,7 @@ Choose "speak" and provide your next utterance, or choose "hangup" if the conver
|
|
|
1009
1038
|
async attachCampaign(campaignCode: string): Promise<void> {
|
|
1010
1039
|
const healthCtx = new HealthContext();
|
|
1011
1040
|
await using _server = await getHealthServer(healthCtx);
|
|
1012
|
-
return this._serveCampaign(healthCtx, campaignCode);
|
|
1041
|
+
return await this._serveCampaign(healthCtx, campaignCode);
|
|
1013
1042
|
}
|
|
1014
1043
|
|
|
1015
1044
|
/* ===== Aliases to be removed at some point. ===== */
|
package/src/call.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type Logger, getDefaultLogger } from "./logging.ts";
|
|
|
2
2
|
import {
|
|
3
3
|
type Command,
|
|
4
4
|
SetPersona,
|
|
5
|
+
type SpeedPreset,
|
|
5
6
|
SetLanguageModeCommand,
|
|
6
7
|
type Language,
|
|
7
8
|
SetTaskCommand,
|
|
@@ -180,6 +181,7 @@ export class Call {
|
|
|
180
181
|
agentName?: string;
|
|
181
182
|
agentPurpose?: string;
|
|
182
183
|
voice?: string;
|
|
184
|
+
speechSpeed?: SpeedPreset;
|
|
183
185
|
pronunciations?: Record<string, string>;
|
|
184
186
|
}) {
|
|
185
187
|
await this.sendCommand(SetPersona, {
|
|
@@ -188,6 +190,7 @@ export class Call {
|
|
|
188
190
|
agent_name: args.agentName,
|
|
189
191
|
agent_purpose: args.agentPurpose,
|
|
190
192
|
voice: args.voice,
|
|
193
|
+
tts_speed: args.speechSpeed,
|
|
191
194
|
tts_replacements: args.pronunciations,
|
|
192
195
|
});
|
|
193
196
|
}
|
package/src/commands.ts
CHANGED
|
@@ -57,12 +57,27 @@ export const AnswerQuestionCommand = z.strictObject({
|
|
|
57
57
|
});
|
|
58
58
|
export type AnswerQuestionCommand = z.input<typeof AnswerQuestionCommand>;
|
|
59
59
|
|
|
60
|
+
export const SpeedPreset = z.enum(["x-slow", "slow", "medium", "fast", "x-fast"]);
|
|
61
|
+
export type SpeedPreset = z.infer<typeof SpeedPreset>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @description throw on an unrecognized speech speed preset, with the valid presets listed
|
|
65
|
+
*/
|
|
66
|
+
export function validateSpeedPreset(speed: unknown): void {
|
|
67
|
+
if (speed !== undefined && !SpeedPreset.safeParse(speed).success) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`speechSpeed must be one of ${JSON.stringify(SpeedPreset.options)} (got ${JSON.stringify(speed)}).`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
export const SetPersona = z.strictObject({
|
|
61
75
|
command_type: z.literal("set-persona"),
|
|
62
76
|
agent_name: z.string().optional(),
|
|
63
77
|
organization_name: z.string().optional(),
|
|
64
78
|
agent_purpose: z.string().optional(),
|
|
65
79
|
voice: z.string().optional(),
|
|
80
|
+
tts_speed: SpeedPreset.optional(),
|
|
66
81
|
tts_replacements: z.record(z.string().min(1), z.string()).optional(),
|
|
67
82
|
});
|
|
68
83
|
export type SetPersona = z.input<typeof SetPersona>;
|
|
@@ -98,6 +113,7 @@ export const RegisteredHooksCommand = z.strictObject({
|
|
|
98
113
|
has_on_action_requested: z.boolean().optional().default(false),
|
|
99
114
|
has_on_escalate: z.boolean().optional().default(false),
|
|
100
115
|
accept_dtmf_for_numbers: z.boolean().default(true),
|
|
116
|
+
has_on_agent_dtmf: z.boolean().optional().default(false),
|
|
101
117
|
});
|
|
102
118
|
export type RegisteredHooksCommand = z.input<typeof RegisteredHooksCommand>;
|
|
103
119
|
|
package/src/events.ts
CHANGED
|
@@ -99,6 +99,7 @@ export const BotSessionEnded = z.object({
|
|
|
99
99
|
"voicemail",
|
|
100
100
|
]),
|
|
101
101
|
dnc: z.boolean().default(false),
|
|
102
|
+
pickup: z.boolean().default(true),
|
|
102
103
|
});
|
|
103
104
|
export type BotSessionEnded = z.infer<typeof BotSessionEnded>;
|
|
104
105
|
|
|
@@ -153,6 +154,17 @@ export const DTMFPressedEvent = z.object({
|
|
|
153
154
|
});
|
|
154
155
|
export type DTMFPressedEvent = z.infer<typeof DTMFPressedEvent>;
|
|
155
156
|
|
|
157
|
+
/**
|
|
158
|
+
* The agent pressed DTMF digits, either on its own after `call.setAgentDtmf(true)`
|
|
159
|
+
* or because the developer called `call.sendDtmf(...)`; `requested_by` says which.
|
|
160
|
+
*/
|
|
161
|
+
export const AgentDTMFSentEvent = z.object({
|
|
162
|
+
event_type: z.literal("agent-dtmf"),
|
|
163
|
+
digits: z.array(z.enum(DTMF_DIGITS)),
|
|
164
|
+
requested_by: z.enum(["agent", "developer"]).default("agent"),
|
|
165
|
+
});
|
|
166
|
+
export type AgentDTMFSentEvent = z.infer<typeof AgentDTMFSentEvent>;
|
|
167
|
+
|
|
156
168
|
export const EscalateEvent = z.object({
|
|
157
169
|
event_type: z.literal("escalate"),
|
|
158
170
|
requested_by: z.enum(["human", "agent"]).default("human"),
|
|
@@ -178,6 +190,7 @@ export const GuavaEvent = z.discriminatedUnion("event_type", [
|
|
|
178
190
|
ExecuteActionEvent,
|
|
179
191
|
EscalateEvent,
|
|
180
192
|
DTMFPressedEvent,
|
|
193
|
+
AgentDTMFSentEvent,
|
|
181
194
|
]);
|
|
182
195
|
export type GuavaEvent = z.infer<typeof GuavaEvent>;
|
|
183
196
|
|
package/src/index.ts
CHANGED
|
@@ -14,10 +14,12 @@ export { Logger, getConsoleLogger, getDefaultLogger } from "./logging.ts";
|
|
|
14
14
|
export { Agent, CallInfo } from "./agent.ts";
|
|
15
15
|
export { Call, DEFAULT_REACH_PERSON_OUTCOMES } from "./call.ts";
|
|
16
16
|
export type { ReachPersonOutcome } from "./call.ts";
|
|
17
|
+
export type { SpeedPreset, Language } from "./commands.ts";
|
|
17
18
|
export type {
|
|
18
19
|
BotSessionEnded,
|
|
19
20
|
TerminationReason,
|
|
20
21
|
DTMFPressedEvent,
|
|
22
|
+
AgentDTMFSentEvent,
|
|
21
23
|
DTMFDigit,
|
|
22
24
|
OutboundCallFailed,
|
|
23
25
|
} from "./events.ts";
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.
|
|
1
|
+
export const SDK_VERSION = "0.35.0";
|