retell-utils 0.3.2 → 0.4.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 +44 -0
- package/dist/agent.d.ts +547 -0
- package/dist/agent.js +226 -0
- package/dist/call.d.ts +16 -16
- package/dist/call.js +2 -2
- package/dist/chat-messages.d.ts +1 -1
- package/dist/enums.d.ts +254 -0
- package/dist/enums.js +239 -0
- package/dist/flow.d.ts +1258 -0
- package/dist/flow.js +152 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +16 -2
- package/dist/llm.d.ts +388 -0
- package/dist/llm.js +118 -0
- package/dist/pagination.d.ts +14 -0
- package/dist/pagination.js +35 -0
- package/dist/phone-number.d.ts +38 -0
- package/dist/phone-number.js +26 -0
- package/dist/phone.d.ts +6 -3
- package/dist/phone.js +10 -3
- package/dist/test-case.d.ts +76 -0
- package/dist/test-case.js +44 -0
- package/dist/transcript.d.ts +2 -2
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +63 -0
- package/dist/webhook.d.ts +16 -16
- package/package.json +4 -4
package/dist/llm.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { KbConfigSchema, McpConfigSchema } from "./agent.js";
|
|
3
|
+
import { LlmModelSchema, LlmToolTypeSchema, S2sModelSchema, StartSpeakerSchema, ToolHttpMethodSchema, ToolParameterTypeSchema, } from "./enums.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Tool sub-schemas
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/** Handoff option within a transfer (prompt the receiving agent, etc.). */
|
|
8
|
+
const HandoffOptionSchema = z.object({
|
|
9
|
+
type: z.string().optional(),
|
|
10
|
+
prompt: z.string().optional(),
|
|
11
|
+
});
|
|
12
|
+
/** Transfer destination configuration. */
|
|
13
|
+
export const TransferDestinationSchema = z.object({
|
|
14
|
+
type: z.string().optional(),
|
|
15
|
+
prompt: z.string().optional(),
|
|
16
|
+
number: z.string().optional(),
|
|
17
|
+
extension: z.string().optional(),
|
|
18
|
+
});
|
|
19
|
+
/** Transfer option configuration (warm/cold transfer behavior). */
|
|
20
|
+
export const TransferOptionSchema = z.object({
|
|
21
|
+
type: z.string().optional(),
|
|
22
|
+
option: HandoffOptionSchema.optional(),
|
|
23
|
+
public_handoff_option: HandoffOptionSchema.optional(),
|
|
24
|
+
private_handoff_option: HandoffOptionSchema.optional(),
|
|
25
|
+
on_hold_music: z.string().optional(),
|
|
26
|
+
opt_out_initial_message: z.boolean().optional(),
|
|
27
|
+
opt_out_human_detection: z.boolean().optional(),
|
|
28
|
+
agent_detection_timeout_ms: z.number().optional(),
|
|
29
|
+
show_transferee_as_caller: z.boolean().optional(),
|
|
30
|
+
enable_bridge_audio_cue: z.boolean().optional(),
|
|
31
|
+
});
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Tools & states
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Schema for an LLM tool. Tools are highly polymorphic (end_call,
|
|
37
|
+
* transfer_call, custom, cal, etc.) so we explicitly declare all known fields
|
|
38
|
+
* and use catchall to preserve any we haven't seen yet.
|
|
39
|
+
*/
|
|
40
|
+
export const LlmToolSchema = z.object({
|
|
41
|
+
// Common
|
|
42
|
+
type: LlmToolTypeSchema,
|
|
43
|
+
name: z.string().optional(),
|
|
44
|
+
description: z.string().optional(),
|
|
45
|
+
tool_id: z.string().optional(),
|
|
46
|
+
// Custom tool HTTP config
|
|
47
|
+
url: z.string().optional(),
|
|
48
|
+
method: ToolHttpMethodSchema.optional(),
|
|
49
|
+
parameter_type: ToolParameterTypeSchema.optional(),
|
|
50
|
+
parameters: z.unknown().optional(),
|
|
51
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
52
|
+
query_params: z.record(z.string(), z.string()).optional(),
|
|
53
|
+
args_at_root: z.boolean().optional(),
|
|
54
|
+
timeout_ms: z.number().optional(),
|
|
55
|
+
response_variables: z.record(z.string(), z.string()).optional(),
|
|
56
|
+
// Speech behavior
|
|
57
|
+
speak_during_execution: z.boolean().optional(),
|
|
58
|
+
speak_after_execution: z.boolean().optional(),
|
|
59
|
+
execution_message_description: z.string().optional(),
|
|
60
|
+
// Transfer
|
|
61
|
+
transfer_destination: TransferDestinationSchema.optional(),
|
|
62
|
+
transfer_option: TransferOptionSchema.optional(),
|
|
63
|
+
custom_sip_headers: z.record(z.string(), z.string()).optional(),
|
|
64
|
+
// Cal.com integration
|
|
65
|
+
cal_api_key: z.string().optional(),
|
|
66
|
+
event_type_id: z.number().optional(),
|
|
67
|
+
timezone: z.string().optional(),
|
|
68
|
+
});
|
|
69
|
+
/** State transition edge within multi-prompt LLM. */
|
|
70
|
+
export const LlmStateEdgeSchema = z.object({
|
|
71
|
+
destination_state_name: z.string(),
|
|
72
|
+
description: z.string().optional(),
|
|
73
|
+
parameters: z.unknown().optional(),
|
|
74
|
+
});
|
|
75
|
+
/** A state within a multi-prompt LLM. */
|
|
76
|
+
export const LlmStateSchema = z.object({
|
|
77
|
+
name: z.string(),
|
|
78
|
+
state_prompt: z.string().optional(),
|
|
79
|
+
edges: z.array(LlmStateEdgeSchema).optional(),
|
|
80
|
+
tools: z.array(LlmToolSchema).nullable().optional(),
|
|
81
|
+
});
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// LLM response
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
/** Zod schema for a Retell LLM response from the API. */
|
|
86
|
+
export const LlmResponseSchema = z.object({
|
|
87
|
+
// Required
|
|
88
|
+
llm_id: z.string(),
|
|
89
|
+
last_modification_timestamp: z.number(),
|
|
90
|
+
// Version
|
|
91
|
+
version: z.number().optional(),
|
|
92
|
+
is_published: z.boolean().optional(),
|
|
93
|
+
// Model selection
|
|
94
|
+
model: LlmModelSchema.nullable().optional(),
|
|
95
|
+
s2s_model: S2sModelSchema.nullable().optional(),
|
|
96
|
+
model_temperature: z.number().optional(),
|
|
97
|
+
model_high_priority: z.boolean().nullable().optional(),
|
|
98
|
+
tool_call_strict_mode: z.boolean().nullable().optional(),
|
|
99
|
+
// Knowledge base
|
|
100
|
+
knowledge_base_ids: z.array(z.string()).nullable().optional(),
|
|
101
|
+
kb_config: KbConfigSchema.nullable().optional(),
|
|
102
|
+
// Conversation
|
|
103
|
+
start_speaker: StartSpeakerSchema.optional(),
|
|
104
|
+
begin_after_user_silence_ms: z.number().nullable().optional(),
|
|
105
|
+
begin_message: z.string().nullable().optional(),
|
|
106
|
+
general_prompt: z.string().nullable().optional(),
|
|
107
|
+
// Tools & states
|
|
108
|
+
general_tools: z.array(LlmToolSchema).nullable().optional(),
|
|
109
|
+
states: z.array(LlmStateSchema).nullable().optional(),
|
|
110
|
+
starting_state: z.string().nullable().optional(),
|
|
111
|
+
// Dynamic variables
|
|
112
|
+
default_dynamic_variables: z
|
|
113
|
+
.record(z.string(), z.string())
|
|
114
|
+
.nullable()
|
|
115
|
+
.optional(),
|
|
116
|
+
// MCP
|
|
117
|
+
mcps: z.array(McpConfigSchema).nullable().optional(),
|
|
118
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches all pages from a paginated Retell API list endpoint. The Retell API
|
|
3
|
+
* uses cursor-based pagination where the last item's ID and version are passed
|
|
4
|
+
* as the cursor for the next page.
|
|
5
|
+
*/
|
|
6
|
+
export declare function retellPagination<T>(
|
|
7
|
+
/** The list API call, receiving pagination options. */
|
|
8
|
+
op: (opts: {
|
|
9
|
+
limit?: number;
|
|
10
|
+
pagination_key?: string;
|
|
11
|
+
pagination_key_version?: number;
|
|
12
|
+
}) => Promise<T[]>,
|
|
13
|
+
/** The property name used as the pagination key (e.g. "agent_id", "llm_id"). */
|
|
14
|
+
idKey: keyof T & string, limit?: number): Promise<T[]>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches all pages from a paginated Retell API list endpoint. The Retell API
|
|
3
|
+
* uses cursor-based pagination where the last item's ID and version are passed
|
|
4
|
+
* as the cursor for the next page.
|
|
5
|
+
*/
|
|
6
|
+
export async function retellPagination(
|
|
7
|
+
/** The list API call, receiving pagination options. */
|
|
8
|
+
op,
|
|
9
|
+
/** The property name used as the pagination key (e.g. "agent_id", "llm_id"). */
|
|
10
|
+
idKey, limit = 1000) {
|
|
11
|
+
const results = [];
|
|
12
|
+
let paginationKey;
|
|
13
|
+
let paginationKeyVersion;
|
|
14
|
+
while (true) {
|
|
15
|
+
const page = await op({
|
|
16
|
+
limit,
|
|
17
|
+
pagination_key: paginationKey,
|
|
18
|
+
pagination_key_version: paginationKeyVersion,
|
|
19
|
+
});
|
|
20
|
+
for (const item of page)
|
|
21
|
+
results.push(item);
|
|
22
|
+
if (page.length < limit)
|
|
23
|
+
break;
|
|
24
|
+
const lastItem = page.at(-1);
|
|
25
|
+
if (!lastItem)
|
|
26
|
+
break;
|
|
27
|
+
const id = lastItem[idKey];
|
|
28
|
+
if (typeof id !== "string")
|
|
29
|
+
break;
|
|
30
|
+
paginationKey = id;
|
|
31
|
+
const version = lastItem.version;
|
|
32
|
+
paginationKeyVersion = typeof version === "number" ? version : undefined;
|
|
33
|
+
}
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Weighted agent entry used in phone number inbound/outbound lists. */
|
|
3
|
+
export declare const PhoneNumberAgentEntrySchema: z.ZodObject<{
|
|
4
|
+
agent_id: z.ZodString;
|
|
5
|
+
agent_version: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
weight: z.ZodNumber;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
/** Zod schema for a phone number response from the Retell API. */
|
|
9
|
+
export declare const PhoneNumberResponseSchema: z.ZodObject<{
|
|
10
|
+
phone_number: z.ZodString;
|
|
11
|
+
phone_number_type: z.ZodOptional<z.ZodEnum<{
|
|
12
|
+
custom: "custom";
|
|
13
|
+
"retell-twilio": "retell-twilio";
|
|
14
|
+
"retell-telnyx": "retell-telnyx";
|
|
15
|
+
}>>;
|
|
16
|
+
nickname: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
17
|
+
last_modification_timestamp: z.ZodNumber;
|
|
18
|
+
inbound_agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
19
|
+
agent_id: z.ZodString;
|
|
20
|
+
agent_version: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
weight: z.ZodNumber;
|
|
22
|
+
}, z.core.$strip>>>>;
|
|
23
|
+
outbound_agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
24
|
+
agent_id: z.ZodString;
|
|
25
|
+
agent_version: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
weight: z.ZodNumber;
|
|
27
|
+
}, z.core.$strip>>>>;
|
|
28
|
+
inbound_sms_agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
29
|
+
agent_id: z.ZodString;
|
|
30
|
+
agent_version: z.ZodOptional<z.ZodNumber>;
|
|
31
|
+
weight: z.ZodNumber;
|
|
32
|
+
}, z.core.$strip>>>>;
|
|
33
|
+
outbound_sms_agents: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
34
|
+
agent_id: z.ZodString;
|
|
35
|
+
agent_version: z.ZodOptional<z.ZodNumber>;
|
|
36
|
+
weight: z.ZodNumber;
|
|
37
|
+
}, z.core.$strip>>>>;
|
|
38
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Weighted agent entry used in phone number inbound/outbound lists. */
|
|
3
|
+
export const PhoneNumberAgentEntrySchema = z.object({
|
|
4
|
+
agent_id: z.string(),
|
|
5
|
+
agent_version: z.number().optional(),
|
|
6
|
+
weight: z.number(),
|
|
7
|
+
});
|
|
8
|
+
/** Zod schema for a phone number response from the Retell API. */
|
|
9
|
+
export const PhoneNumberResponseSchema = z.object({
|
|
10
|
+
phone_number: z.string(),
|
|
11
|
+
phone_number_type: z
|
|
12
|
+
.enum(["retell-twilio", "retell-telnyx", "custom"])
|
|
13
|
+
.optional(),
|
|
14
|
+
nickname: z.string().nullable().optional(),
|
|
15
|
+
last_modification_timestamp: z.number(),
|
|
16
|
+
inbound_agents: z.array(PhoneNumberAgentEntrySchema).nullable().optional(),
|
|
17
|
+
outbound_agents: z.array(PhoneNumberAgentEntrySchema).nullable().optional(),
|
|
18
|
+
inbound_sms_agents: z
|
|
19
|
+
.array(PhoneNumberAgentEntrySchema)
|
|
20
|
+
.nullable()
|
|
21
|
+
.optional(),
|
|
22
|
+
outbound_sms_agents: z
|
|
23
|
+
.array(PhoneNumberAgentEntrySchema)
|
|
24
|
+
.nullable()
|
|
25
|
+
.optional(),
|
|
26
|
+
});
|
package/dist/phone.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Validates and normalizes a phone number to E.164 format (`+` followed by 1–15
|
|
4
|
+
* digits).
|
|
5
|
+
*/
|
|
6
|
+
export declare const e164PhoneSchema: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
4
7
|
/**
|
|
5
8
|
* E.164 phone number or null. Invalid, empty, or missing numbers are caught as
|
|
6
9
|
* null — useful for `from_number` where caller ID may be unavailable.
|
|
7
10
|
*/
|
|
8
|
-
export declare const e164OrNullSchema: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
11
|
+
export declare const e164OrNullSchema: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
package/dist/phone.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { parsePhoneNumberFromString } from "libphonenumber-js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates and normalizes a phone number to E.164 format (`+` followed by 1–15
|
|
5
|
+
* digits).
|
|
6
|
+
*/
|
|
7
|
+
export const e164PhoneSchema = z
|
|
8
|
+
.string()
|
|
9
|
+
.transform((v) => parsePhoneNumberFromString(v, "US")?.format("E.164"))
|
|
10
|
+
.pipe(z.string().regex(/^\+[1-9]\d{1,14}$/));
|
|
4
11
|
/**
|
|
5
12
|
* E.164 phone number or null. Invalid, empty, or missing numbers are caught as
|
|
6
13
|
* null — useful for `from_number` where caller ID may be unavailable.
|
|
7
14
|
*/
|
|
8
|
-
export const e164OrNullSchema =
|
|
15
|
+
export const e164OrNullSchema = e164PhoneSchema.nullable().catch(null);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Zod schema for input match rule types in test case tool mocks. */
|
|
3
|
+
export declare const InputMatchRuleSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4
|
+
type: z.ZodLiteral<"any">;
|
|
5
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
6
|
+
type: z.ZodLiteral<"partial_match">;
|
|
7
|
+
args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
8
|
+
}, z.core.$strip>], "type">;
|
|
9
|
+
/** Zod schema for tool mock configurations in test cases. */
|
|
10
|
+
export declare const ToolMockSchema: z.ZodObject<{
|
|
11
|
+
tool_name: z.ZodString;
|
|
12
|
+
input_match_rule: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13
|
+
type: z.ZodLiteral<"any">;
|
|
14
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
15
|
+
type: z.ZodLiteral<"partial_match">;
|
|
16
|
+
args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
17
|
+
}, z.core.$strip>], "type">;
|
|
18
|
+
output: z.ZodString;
|
|
19
|
+
result: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
/** Zod schema for response engine references in test cases. */
|
|
22
|
+
export declare const TestCaseResponseEngineSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
23
|
+
type: z.ZodLiteral<"retell-llm">;
|
|
24
|
+
llm_id: z.ZodString;
|
|
25
|
+
version: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
type: z.ZodLiteral<"conversation-flow">;
|
|
28
|
+
conversation_flow_id: z.ZodString;
|
|
29
|
+
version: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
}, z.core.$strip>], "type">;
|
|
31
|
+
/** Zod schema for a test case definition from the Retell API. */
|
|
32
|
+
export declare const TestCaseDefinitionSchema: z.ZodObject<{
|
|
33
|
+
test_case_definition_id: z.ZodString;
|
|
34
|
+
name: z.ZodString;
|
|
35
|
+
response_engine: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
36
|
+
type: z.ZodLiteral<"retell-llm">;
|
|
37
|
+
llm_id: z.ZodString;
|
|
38
|
+
version: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
40
|
+
type: z.ZodLiteral<"conversation-flow">;
|
|
41
|
+
conversation_flow_id: z.ZodString;
|
|
42
|
+
version: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
}, z.core.$strip>], "type">;
|
|
44
|
+
dynamic_variables: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
45
|
+
metrics: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
46
|
+
user_prompt: z.ZodString;
|
|
47
|
+
creation_timestamp: z.ZodNumber;
|
|
48
|
+
user_modified_timestamp: z.ZodNumber;
|
|
49
|
+
type: z.ZodLiteral<"simulation">;
|
|
50
|
+
tool_mocks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
51
|
+
tool_name: z.ZodString;
|
|
52
|
+
input_match_rule: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
53
|
+
type: z.ZodLiteral<"any">;
|
|
54
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
55
|
+
type: z.ZodLiteral<"partial_match">;
|
|
56
|
+
args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
57
|
+
}, z.core.$strip>], "type">;
|
|
58
|
+
output: z.ZodString;
|
|
59
|
+
result: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
60
|
+
}, z.core.$strip>>>>;
|
|
61
|
+
llm_model: z.ZodEnum<{
|
|
62
|
+
"gpt-4.1": "gpt-4.1";
|
|
63
|
+
"gpt-4.1-mini": "gpt-4.1-mini";
|
|
64
|
+
"gpt-4.1-nano": "gpt-4.1-nano";
|
|
65
|
+
"gpt-5": "gpt-5";
|
|
66
|
+
"gpt-5.1": "gpt-5.1";
|
|
67
|
+
"gpt-5.2": "gpt-5.2";
|
|
68
|
+
"gpt-5-mini": "gpt-5-mini";
|
|
69
|
+
"gpt-5-nano": "gpt-5-nano";
|
|
70
|
+
"claude-4.5-sonnet": "claude-4.5-sonnet";
|
|
71
|
+
"claude-4.5-haiku": "claude-4.5-haiku";
|
|
72
|
+
"gemini-2.5-flash": "gemini-2.5-flash";
|
|
73
|
+
"gemini-2.5-flash-lite": "gemini-2.5-flash-lite";
|
|
74
|
+
"gemini-3.0-flash": "gemini-3.0-flash";
|
|
75
|
+
}>;
|
|
76
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { LlmModelSchema } from "./enums.js";
|
|
3
|
+
/** Zod schema for input match rule types in test case tool mocks. */
|
|
4
|
+
export const InputMatchRuleSchema = z.discriminatedUnion("type", [
|
|
5
|
+
z.object({ type: z.literal("any") }),
|
|
6
|
+
z.object({
|
|
7
|
+
type: z.literal("partial_match"),
|
|
8
|
+
args: z.record(z.string(), z.unknown()),
|
|
9
|
+
}),
|
|
10
|
+
]);
|
|
11
|
+
/** Zod schema for tool mock configurations in test cases. */
|
|
12
|
+
export const ToolMockSchema = z.object({
|
|
13
|
+
tool_name: z.string(),
|
|
14
|
+
input_match_rule: InputMatchRuleSchema,
|
|
15
|
+
output: z.string(),
|
|
16
|
+
result: z.boolean().nullable().optional(),
|
|
17
|
+
});
|
|
18
|
+
/** Zod schema for response engine references in test cases. */
|
|
19
|
+
export const TestCaseResponseEngineSchema = z.discriminatedUnion("type", [
|
|
20
|
+
z.object({
|
|
21
|
+
type: z.literal("retell-llm"),
|
|
22
|
+
llm_id: z.string(),
|
|
23
|
+
version: z.number().optional(),
|
|
24
|
+
}),
|
|
25
|
+
z.object({
|
|
26
|
+
type: z.literal("conversation-flow"),
|
|
27
|
+
conversation_flow_id: z.string(),
|
|
28
|
+
version: z.number().optional(),
|
|
29
|
+
}),
|
|
30
|
+
]);
|
|
31
|
+
/** Zod schema for a test case definition from the Retell API. */
|
|
32
|
+
export const TestCaseDefinitionSchema = z.object({
|
|
33
|
+
test_case_definition_id: z.string(),
|
|
34
|
+
name: z.string(),
|
|
35
|
+
response_engine: TestCaseResponseEngineSchema,
|
|
36
|
+
dynamic_variables: z.record(z.string(), z.unknown()).optional().default({}),
|
|
37
|
+
metrics: z.array(z.string()).optional().default([]),
|
|
38
|
+
user_prompt: z.string(),
|
|
39
|
+
creation_timestamp: z.number(),
|
|
40
|
+
user_modified_timestamp: z.number(),
|
|
41
|
+
type: z.literal("simulation"),
|
|
42
|
+
tool_mocks: z.array(ToolMockSchema).optional().default([]),
|
|
43
|
+
llm_model: LlmModelSchema,
|
|
44
|
+
});
|
package/dist/transcript.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export declare const WordTimestampSchema: z.ZodObject<{
|
|
|
11
11
|
*/
|
|
12
12
|
export declare const UtteranceSchema: z.ZodObject<{
|
|
13
13
|
role: z.ZodEnum<{
|
|
14
|
-
agent: "agent";
|
|
15
14
|
user: "user";
|
|
15
|
+
agent: "agent";
|
|
16
16
|
transfer_target: "transfer_target";
|
|
17
17
|
}>;
|
|
18
18
|
content: z.ZodString;
|
|
@@ -113,8 +113,8 @@ export declare const TranscriptEntrySchema: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
113
113
|
*/
|
|
114
114
|
export declare const TimestampedUtteranceSchema: z.ZodObject<{
|
|
115
115
|
role: z.ZodEnum<{
|
|
116
|
-
agent: "agent";
|
|
117
116
|
user: "user";
|
|
117
|
+
agent: "agent";
|
|
118
118
|
transfer_target: "transfer_target";
|
|
119
119
|
}>;
|
|
120
120
|
content: z.ZodString;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Converts a string to snake_case, stripping non-alphanumeric characters. */
|
|
2
|
+
export declare function toSnakeCase(str: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Simple English pluralizer. Handles common suffix rules (-y -> -ies, add -s).
|
|
5
|
+
* Optionally prefixes the quantity.
|
|
6
|
+
*/
|
|
7
|
+
export declare function pluralize(word: string, q: number, includeQuantity?: boolean): string;
|
|
8
|
+
/**
|
|
9
|
+
* Recursively searches through an object/array structure and replaces `file://`
|
|
10
|
+
* placeholders with resolved file contents. Mutates the structure in place.
|
|
11
|
+
*
|
|
12
|
+
* @param resolveFileContent Called with the relative file path (after stripping
|
|
13
|
+
* the `file://` prefix) and should return the raw file content.
|
|
14
|
+
* @param transformContent Optional post-processor applied to each resolved
|
|
15
|
+
* file's content before it replaces the placeholder (e.g. strip YAML
|
|
16
|
+
* frontmatter from markdown).
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveFilePlaceholders(value: unknown, resolveFileContent: (filePath: string) => string | Promise<string>, transformContent?: (content: string) => string | Promise<string>): Promise<void>;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Converts a string to snake_case, stripping non-alphanumeric characters. */
|
|
2
|
+
export function toSnakeCase(str) {
|
|
3
|
+
return str
|
|
4
|
+
.replace(/\s+/g, "_")
|
|
5
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
6
|
+
.replace(/[^a-z0-9_]/gi, "")
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/_+/g, "_")
|
|
9
|
+
.replace(/^_|_$/g, "");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Simple English pluralizer. Handles common suffix rules (-y -> -ies, add -s).
|
|
13
|
+
* Optionally prefixes the quantity.
|
|
14
|
+
*/
|
|
15
|
+
export function pluralize(word, q, includeQuantity = false) {
|
|
16
|
+
let pluralWord = word;
|
|
17
|
+
if (q !== 1) {
|
|
18
|
+
if (word.endsWith("y") && !/[aeiou]y$/i.test(word)) {
|
|
19
|
+
pluralWord = `${word.slice(0, -1)}ies`;
|
|
20
|
+
}
|
|
21
|
+
else if (!word.endsWith("s")) {
|
|
22
|
+
pluralWord = `${word}s`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const quantity = includeQuantity ? `${q} ` : "";
|
|
26
|
+
return `${quantity}${pluralWord}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Recursively searches through an object/array structure and replaces `file://`
|
|
30
|
+
* placeholders with resolved file contents. Mutates the structure in place.
|
|
31
|
+
*
|
|
32
|
+
* @param resolveFileContent Called with the relative file path (after stripping
|
|
33
|
+
* the `file://` prefix) and should return the raw file content.
|
|
34
|
+
* @param transformContent Optional post-processor applied to each resolved
|
|
35
|
+
* file's content before it replaces the placeholder (e.g. strip YAML
|
|
36
|
+
* frontmatter from markdown).
|
|
37
|
+
*/
|
|
38
|
+
export async function resolveFilePlaceholders(value, resolveFileContent, transformContent) {
|
|
39
|
+
const resolveValue = async (val) => {
|
|
40
|
+
if (typeof val !== "string" || !val.startsWith("file://"))
|
|
41
|
+
return undefined;
|
|
42
|
+
const filePath = val.slice(7); // strip "file://"
|
|
43
|
+
const content = await resolveFileContent(filePath);
|
|
44
|
+
return transformContent ? transformContent(content) : content;
|
|
45
|
+
};
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
await Promise.all(value.map(async (item, i) => {
|
|
48
|
+
const resolved = await resolveValue(item);
|
|
49
|
+
if (resolved)
|
|
50
|
+
value[i] = resolved;
|
|
51
|
+
await resolveFilePlaceholders(item, resolveFileContent, transformContent);
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
else if (value != null && typeof value === "object") {
|
|
55
|
+
const record = value;
|
|
56
|
+
await Promise.all(Object.entries(record).map(async ([key, propValue]) => {
|
|
57
|
+
const resolved = await resolveValue(propValue);
|
|
58
|
+
if (resolved)
|
|
59
|
+
record[key] = resolved;
|
|
60
|
+
await resolveFilePlaceholders(propValue, resolveFileContent, transformContent);
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
}
|
package/dist/webhook.d.ts
CHANGED
|
@@ -140,8 +140,8 @@ export declare const WebhookSchemas: {
|
|
|
140
140
|
}, z.core.$strip>], "role">>>;
|
|
141
141
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
142
142
|
call_type: z.ZodLiteral<"phone_call">;
|
|
143
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
144
|
-
to_number: z.ZodString
|
|
143
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
144
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
145
145
|
direction: z.ZodEnum<{
|
|
146
146
|
inbound: "inbound";
|
|
147
147
|
outbound: "outbound";
|
|
@@ -231,8 +231,8 @@ export declare const WebhookSchemas: {
|
|
|
231
231
|
}, z.core.$strip>], "role">>>;
|
|
232
232
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
233
233
|
call_type: z.ZodLiteral<"phone_call">;
|
|
234
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
235
|
-
to_number: z.ZodString
|
|
234
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
235
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
236
236
|
direction: z.ZodEnum<{
|
|
237
237
|
inbound: "inbound";
|
|
238
238
|
outbound: "outbound";
|
|
@@ -279,8 +279,8 @@ export declare const WebhookSchemas: {
|
|
|
279
279
|
transcript: z.ZodOptional<z.ZodString>;
|
|
280
280
|
transcript_object: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
281
281
|
role: z.ZodEnum<{
|
|
282
|
-
agent: "agent";
|
|
283
282
|
user: "user";
|
|
283
|
+
agent: "agent";
|
|
284
284
|
transfer_target: "transfer_target";
|
|
285
285
|
}>;
|
|
286
286
|
content: z.ZodString;
|
|
@@ -515,8 +515,8 @@ export declare const WebhookSchemas: {
|
|
|
515
515
|
}, z.core.$strip>], "role">>>;
|
|
516
516
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
517
517
|
call_type: z.ZodLiteral<"phone_call">;
|
|
518
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
519
|
-
to_number: z.ZodString
|
|
518
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
519
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
520
520
|
direction: z.ZodEnum<{
|
|
521
521
|
inbound: "inbound";
|
|
522
522
|
outbound: "outbound";
|
|
@@ -563,8 +563,8 @@ export declare const WebhookSchemas: {
|
|
|
563
563
|
transcript: z.ZodOptional<z.ZodString>;
|
|
564
564
|
transcript_object: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
565
565
|
role: z.ZodEnum<{
|
|
566
|
-
agent: "agent";
|
|
567
566
|
user: "user";
|
|
567
|
+
agent: "agent";
|
|
568
568
|
transfer_target: "transfer_target";
|
|
569
569
|
}>;
|
|
570
570
|
content: z.ZodString;
|
|
@@ -968,8 +968,8 @@ export declare const WebhookSchemas: {
|
|
|
968
968
|
}, z.core.$strip>], "role">>>;
|
|
969
969
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
970
970
|
call_type: z.ZodLiteral<"phone_call">;
|
|
971
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
972
|
-
to_number: z.ZodString
|
|
971
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
972
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
973
973
|
direction: z.ZodEnum<{
|
|
974
974
|
inbound: "inbound";
|
|
975
975
|
outbound: "outbound";
|
|
@@ -1058,8 +1058,8 @@ export declare const WebhookSchemas: {
|
|
|
1058
1058
|
}, z.core.$strip>], "role">>>;
|
|
1059
1059
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1060
1060
|
call_type: z.ZodLiteral<"phone_call">;
|
|
1061
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
1062
|
-
to_number: z.ZodString
|
|
1061
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
1062
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
1063
1063
|
direction: z.ZodEnum<{
|
|
1064
1064
|
inbound: "inbound";
|
|
1065
1065
|
outbound: "outbound";
|
|
@@ -1106,8 +1106,8 @@ export declare const WebhookSchemas: {
|
|
|
1106
1106
|
transcript: z.ZodOptional<z.ZodString>;
|
|
1107
1107
|
transcript_object: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1108
1108
|
role: z.ZodEnum<{
|
|
1109
|
-
agent: "agent";
|
|
1110
1109
|
user: "user";
|
|
1110
|
+
agent: "agent";
|
|
1111
1111
|
transfer_target: "transfer_target";
|
|
1112
1112
|
}>;
|
|
1113
1113
|
content: z.ZodString;
|
|
@@ -1341,8 +1341,8 @@ export declare const WebhookSchemas: {
|
|
|
1341
1341
|
}, z.core.$strip>], "role">>>;
|
|
1342
1342
|
}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1343
1343
|
call_type: z.ZodLiteral<"phone_call">;
|
|
1344
|
-
from_number: z.ZodCatch<z.ZodNullable<z.ZodString
|
|
1345
|
-
to_number: z.ZodString
|
|
1344
|
+
from_number: z.ZodCatch<z.ZodNullable<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>>>;
|
|
1345
|
+
to_number: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>, z.ZodString>;
|
|
1346
1346
|
direction: z.ZodEnum<{
|
|
1347
1347
|
inbound: "inbound";
|
|
1348
1348
|
outbound: "outbound";
|
|
@@ -1389,8 +1389,8 @@ export declare const WebhookSchemas: {
|
|
|
1389
1389
|
transcript: z.ZodOptional<z.ZodString>;
|
|
1390
1390
|
transcript_object: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1391
1391
|
role: z.ZodEnum<{
|
|
1392
|
-
agent: "agent";
|
|
1393
1392
|
user: "user";
|
|
1393
|
+
agent: "agent";
|
|
1394
1394
|
transfer_target: "transfer_target";
|
|
1395
1395
|
}>;
|
|
1396
1396
|
content: z.ZodString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "retell-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Type-safe Zod schemas for Retell AI API resources with lifecycle-aware discriminated unions and generic customization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"zshy": {
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
"test": "bun test",
|
|
18
18
|
"prepublishOnly": "bun run build"
|
|
19
19
|
},
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"libphonenumber-js": "^1.12.36",
|
|
22
|
+
"zod": "^4.3.5"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/bun": "latest",
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
"prettier": "latest",
|
|
28
29
|
"prettier-plugin-jsdoc": "^1.8.0",
|
|
29
30
|
"typescript": "^5.8.3",
|
|
30
|
-
"zod": "^4.3.5",
|
|
31
31
|
"zshy": "^0.7.0"
|
|
32
32
|
},
|
|
33
33
|
"license": "MIT",
|