retell-cli 1.4.2 → 1.6.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/CHANGELOG.md +86 -0
- package/README.md +139 -4
- package/dist/index.js +2001 -258
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/index.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
|
-
var
|
|
28
|
+
var import_fs19 = require("fs");
|
|
29
29
|
var import_path6 = require("path");
|
|
30
30
|
|
|
31
31
|
// src/commands/login.ts
|
|
@@ -383,13 +383,13 @@ function getRetellClient() {
|
|
|
383
383
|
async function listTranscriptsCommand(options) {
|
|
384
384
|
try {
|
|
385
385
|
const client = getRetellClient();
|
|
386
|
-
const
|
|
386
|
+
const calls2 = await client.call.list({
|
|
387
387
|
limit: options.limit || 50
|
|
388
388
|
});
|
|
389
389
|
const output = options.fields ? filterFields(
|
|
390
|
-
|
|
390
|
+
calls2,
|
|
391
391
|
options.fields.split(",").map((f) => f.trim())
|
|
392
|
-
) :
|
|
392
|
+
) : calls2;
|
|
393
393
|
outputJson(output);
|
|
394
394
|
} catch (error) {
|
|
395
395
|
handleSdkError(error);
|
|
@@ -3640,10 +3640,9 @@ async function addKnowledgeBaseSourcesCommand(knowledgeBaseId, options) {
|
|
|
3640
3640
|
async function deleteKnowledgeBaseSourceCommand(knowledgeBaseId, sourceId) {
|
|
3641
3641
|
try {
|
|
3642
3642
|
const client = getRetellClient();
|
|
3643
|
-
const knowledgeBase = await client.knowledgeBase.deleteSource(
|
|
3644
|
-
knowledgeBaseId
|
|
3645
|
-
|
|
3646
|
-
);
|
|
3643
|
+
const knowledgeBase = await client.knowledgeBase.deleteSource(sourceId, {
|
|
3644
|
+
knowledge_base_id: knowledgeBaseId
|
|
3645
|
+
});
|
|
3647
3646
|
const output = {
|
|
3648
3647
|
message: "Source deleted successfully",
|
|
3649
3648
|
knowledge_base_id: knowledgeBase.knowledge_base_id,
|
|
@@ -3818,8 +3817,8 @@ async function listPhoneNumbersCommand(options = {}) {
|
|
|
3818
3817
|
phone_number_pretty: pn.phone_number_pretty,
|
|
3819
3818
|
phone_number_type: pn.phone_number_type,
|
|
3820
3819
|
nickname: pn.nickname,
|
|
3821
|
-
|
|
3822
|
-
|
|
3820
|
+
inbound_agents: pn.inbound_agents ?? [],
|
|
3821
|
+
outbound_agents: pn.outbound_agents ?? []
|
|
3823
3822
|
}));
|
|
3824
3823
|
const output = options.fields ? filterFields(
|
|
3825
3824
|
formatted,
|
|
@@ -3846,29 +3845,146 @@ async function getPhoneNumberCommand(phoneNumber, options = {}) {
|
|
|
3846
3845
|
}
|
|
3847
3846
|
}
|
|
3848
3847
|
|
|
3848
|
+
// src/services/weighted-agents.ts
|
|
3849
|
+
function parseWeightedAgents(spec) {
|
|
3850
|
+
const entries = spec.split(",").map((s) => s.trim()).filter(Boolean);
|
|
3851
|
+
if (entries.length === 0) {
|
|
3852
|
+
throwValidation("Empty agent spec. Provide at least one agent ID.");
|
|
3853
|
+
}
|
|
3854
|
+
const agents2 = entries.map((entry) => {
|
|
3855
|
+
const parts = entry.split(":");
|
|
3856
|
+
if (parts.length > 2) {
|
|
3857
|
+
throwValidation(
|
|
3858
|
+
`Invalid agent spec "${entry}". Expected format: agent_id or agent_id:weight`
|
|
3859
|
+
);
|
|
3860
|
+
}
|
|
3861
|
+
const agentId = parts[0].trim();
|
|
3862
|
+
if (!agentId) {
|
|
3863
|
+
throwValidation(`Invalid agent spec "${entry}". Agent ID is empty.`);
|
|
3864
|
+
}
|
|
3865
|
+
if (parts.length === 1) {
|
|
3866
|
+
return { agent_id: agentId, weight: -1 };
|
|
3867
|
+
}
|
|
3868
|
+
const weight = Number(parts[1]);
|
|
3869
|
+
if (isNaN(weight) || weight <= 0 || weight > 1) {
|
|
3870
|
+
throwValidation(
|
|
3871
|
+
`Invalid weight "${parts[1]}" for agent "${agentId}". Weight must be a number between 0 (exclusive) and 1 (inclusive).`
|
|
3872
|
+
);
|
|
3873
|
+
}
|
|
3874
|
+
return { agent_id: agentId, weight };
|
|
3875
|
+
});
|
|
3876
|
+
const allDefault = agents2.every((a) => a.weight === -1);
|
|
3877
|
+
if (allDefault) {
|
|
3878
|
+
const w = 1 / agents2.length;
|
|
3879
|
+
for (const a of agents2) a.weight = w;
|
|
3880
|
+
} else if (agents2.some((a) => a.weight === -1)) {
|
|
3881
|
+
throwValidation(
|
|
3882
|
+
"Cannot mix agents with and without weights. Either specify weights for all agents or none."
|
|
3883
|
+
);
|
|
3884
|
+
}
|
|
3885
|
+
const sum = agents2.reduce((s, a) => s + a.weight, 0);
|
|
3886
|
+
if (Math.abs(sum - 1) > 1e-3) {
|
|
3887
|
+
throwValidation(
|
|
3888
|
+
`Agent weights must sum to 1.0, but got ${sum.toFixed(4)}.`
|
|
3889
|
+
);
|
|
3890
|
+
}
|
|
3891
|
+
return agents2;
|
|
3892
|
+
}
|
|
3893
|
+
function applyWeightedAgents(params, flags, options = { allowSms: true }) {
|
|
3894
|
+
for (const [flagName, val] of [
|
|
3895
|
+
["--inbound-agent", flags.inboundAgent],
|
|
3896
|
+
["--outbound-agent", flags.outboundAgent],
|
|
3897
|
+
["--inbound-agents", flags.inboundAgents],
|
|
3898
|
+
["--outbound-agents", flags.outboundAgents],
|
|
3899
|
+
["--inbound-sms-agents", flags.inboundSmsAgents],
|
|
3900
|
+
["--outbound-sms-agents", flags.outboundSmsAgents]
|
|
3901
|
+
]) {
|
|
3902
|
+
if (val !== void 0 && val.trim() === "") {
|
|
3903
|
+
throwValidation(`${flagName} must not be empty`);
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
if (flags.inboundAgent && flags.inboundAgents) {
|
|
3907
|
+
throwValidation(
|
|
3908
|
+
"--inbound-agent and --inbound-agents are mutually exclusive. Use one or the other."
|
|
3909
|
+
);
|
|
3910
|
+
}
|
|
3911
|
+
if (flags.outboundAgent && flags.outboundAgents) {
|
|
3912
|
+
throwValidation(
|
|
3913
|
+
"--outbound-agent and --outbound-agents are mutually exclusive. Use one or the other."
|
|
3914
|
+
);
|
|
3915
|
+
}
|
|
3916
|
+
if (!options.allowSms && (flags.inboundSmsAgents || flags.outboundSmsAgents)) {
|
|
3917
|
+
throwValidation("SMS agent flags are not supported for this command.");
|
|
3918
|
+
}
|
|
3919
|
+
if (flags.inboundAgent) {
|
|
3920
|
+
params.inbound_agents = [{ agent_id: flags.inboundAgent, weight: 1 }];
|
|
3921
|
+
} else if (flags.inboundAgents) {
|
|
3922
|
+
params.inbound_agents = parseWeightedAgents(flags.inboundAgents);
|
|
3923
|
+
}
|
|
3924
|
+
if (flags.outboundAgent) {
|
|
3925
|
+
params.outbound_agents = [{ agent_id: flags.outboundAgent, weight: 1 }];
|
|
3926
|
+
} else if (flags.outboundAgents) {
|
|
3927
|
+
params.outbound_agents = parseWeightedAgents(flags.outboundAgents);
|
|
3928
|
+
}
|
|
3929
|
+
if (flags.inboundSmsAgents) {
|
|
3930
|
+
params.inbound_sms_agents = parseWeightedAgents(flags.inboundSmsAgents);
|
|
3931
|
+
}
|
|
3932
|
+
if (flags.outboundSmsAgents) {
|
|
3933
|
+
params.outbound_sms_agents = parseWeightedAgents(flags.outboundSmsAgents);
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
function throwValidation(message) {
|
|
3937
|
+
const err = new Error(message);
|
|
3938
|
+
err.name = "ValidationError";
|
|
3939
|
+
throw err;
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3942
|
+
// src/services/flag-guards.ts
|
|
3943
|
+
function requireNonEmpty(value, flagName) {
|
|
3944
|
+
if (value.trim() === "") {
|
|
3945
|
+
throwValidation2(`${flagName} must not be empty`);
|
|
3946
|
+
}
|
|
3947
|
+
return value;
|
|
3948
|
+
}
|
|
3949
|
+
function throwValidation2(message) {
|
|
3950
|
+
const err = new Error(message);
|
|
3951
|
+
err.name = "ValidationError";
|
|
3952
|
+
throw err;
|
|
3953
|
+
}
|
|
3954
|
+
|
|
3849
3955
|
// src/commands/phone-numbers/import.ts
|
|
3850
3956
|
async function importPhoneNumberCommand(options) {
|
|
3851
3957
|
try {
|
|
3852
|
-
const client = getRetellClient();
|
|
3853
3958
|
const importParams = {
|
|
3854
|
-
phone_number: options.number,
|
|
3855
|
-
termination_uri:
|
|
3959
|
+
phone_number: requireNonEmpty(options.number, "--number"),
|
|
3960
|
+
termination_uri: requireNonEmpty(
|
|
3961
|
+
options.terminationUri,
|
|
3962
|
+
"--termination-uri"
|
|
3963
|
+
)
|
|
3856
3964
|
};
|
|
3857
3965
|
if (options.nickname) {
|
|
3858
3966
|
importParams.nickname = options.nickname;
|
|
3859
3967
|
}
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3968
|
+
const weightedFlags = options;
|
|
3969
|
+
applyWeightedAgents(
|
|
3970
|
+
importParams,
|
|
3971
|
+
{
|
|
3972
|
+
inboundAgent: weightedFlags.inboundAgent,
|
|
3973
|
+
outboundAgent: weightedFlags.outboundAgent,
|
|
3974
|
+
inboundAgents: weightedFlags.inboundAgents,
|
|
3975
|
+
outboundAgents: weightedFlags.outboundAgents,
|
|
3976
|
+
inboundSmsAgents: weightedFlags.inboundSmsAgents,
|
|
3977
|
+
outboundSmsAgents: weightedFlags.outboundSmsAgents
|
|
3978
|
+
},
|
|
3979
|
+
{ allowSms: false }
|
|
3980
|
+
);
|
|
3866
3981
|
if (options.sipUsername) {
|
|
3867
3982
|
importParams.sip_trunk_auth_username = options.sipUsername;
|
|
3868
3983
|
}
|
|
3869
3984
|
if (options.sipPassword) {
|
|
3870
3985
|
importParams.sip_trunk_auth_password = options.sipPassword;
|
|
3871
3986
|
}
|
|
3987
|
+
const client = getRetellClient();
|
|
3872
3988
|
const pn = await client.phoneNumber.import(importParams);
|
|
3873
3989
|
const output = options.fields ? filterFields(
|
|
3874
3990
|
pn,
|
|
@@ -3880,235 +3996,1531 @@ async function importPhoneNumberCommand(options) {
|
|
|
3880
3996
|
}
|
|
3881
3997
|
}
|
|
3882
3998
|
|
|
3883
|
-
// src/
|
|
3884
|
-
|
|
3885
|
-
(
|
|
3886
|
-
);
|
|
3887
|
-
var program = new import_commander.Command();
|
|
3888
|
-
program.name("retell").description("Retell AI CLI - Manage transcripts and agent prompts").version(packageJson.version, "-v, --version", "Display version number").helpOption("-h, --help", "Display help for command").option("--json", "Output as JSON (default)", true);
|
|
3889
|
-
program.command("login").description("Authenticate with Retell AI").addHelpText(
|
|
3890
|
-
"after",
|
|
3891
|
-
`
|
|
3892
|
-
Examples:
|
|
3893
|
-
$ retell login
|
|
3894
|
-
# Enter your API key when prompted
|
|
3895
|
-
# Creates .retellrc.json in current directory
|
|
3896
|
-
`
|
|
3897
|
-
).action(async () => {
|
|
3898
|
-
await loginCommand();
|
|
3899
|
-
});
|
|
3900
|
-
var transcripts = program.command("transcripts").description("Manage call transcripts");
|
|
3901
|
-
transcripts.command("list").description("List all call transcripts").option(
|
|
3902
|
-
"-l, --limit <number>",
|
|
3903
|
-
"Maximum number of calls to return (default: 50)",
|
|
3904
|
-
"50"
|
|
3905
|
-
).option(
|
|
3906
|
-
"--fields <fields>",
|
|
3907
|
-
"Comma-separated list of fields to return (e.g., call_id,call_status,metadata.duration)"
|
|
3908
|
-
).addHelpText(
|
|
3909
|
-
"after",
|
|
3910
|
-
`
|
|
3911
|
-
Examples:
|
|
3912
|
-
$ retell transcripts list
|
|
3913
|
-
$ retell transcripts list --limit 100
|
|
3914
|
-
$ retell transcripts list --fields call_id,call_status
|
|
3915
|
-
$ retell transcripts list | jq '.[] | select(.call_status == "error")'
|
|
3916
|
-
`
|
|
3917
|
-
).action(async (options) => {
|
|
3918
|
-
const limit = parseInt(options.limit, 10);
|
|
3919
|
-
if (isNaN(limit) || limit < 1) {
|
|
3920
|
-
console.error("Error: limit must be a positive number");
|
|
3921
|
-
process.exit(1);
|
|
3999
|
+
// src/services/numeric-flag.ts
|
|
4000
|
+
function parseNumericFlag(value, flagName) {
|
|
4001
|
+
if (value.trim() === "") {
|
|
4002
|
+
throwValidation3(`${flagName} must be a number`);
|
|
3922
4003
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
});
|
|
3927
|
-
});
|
|
3928
|
-
transcripts.command("get <call_id>").description("Get a specific call transcript").option(
|
|
3929
|
-
"--fields <fields>",
|
|
3930
|
-
"Comma-separated list of fields to return (e.g., call_id,metadata.duration,analysis)"
|
|
3931
|
-
).addHelpText(
|
|
3932
|
-
"after",
|
|
3933
|
-
`
|
|
3934
|
-
Examples:
|
|
3935
|
-
$ retell transcripts get call_abc123
|
|
3936
|
-
$ retell transcripts get call_abc123 --fields call_id,metadata.duration
|
|
3937
|
-
$ retell transcripts get call_abc123 | jq '.transcript_object'
|
|
3938
|
-
`
|
|
3939
|
-
).action(async (callId, options) => {
|
|
3940
|
-
await getTranscriptCommand(callId, {
|
|
3941
|
-
fields: options.fields
|
|
3942
|
-
});
|
|
3943
|
-
});
|
|
3944
|
-
transcripts.command("analyze <call_id>").description(
|
|
3945
|
-
"Analyze a call transcript with performance metrics and insights"
|
|
3946
|
-
).option(
|
|
3947
|
-
"--fields <fields>",
|
|
3948
|
-
"Comma-separated list of fields to return (e.g., call_id,performance,analysis.summary)"
|
|
3949
|
-
).option(
|
|
3950
|
-
"--raw",
|
|
3951
|
-
"Return unmodified API response instead of enriched analysis"
|
|
3952
|
-
).option(
|
|
3953
|
-
"--hotspots-only",
|
|
3954
|
-
"Return only conversation hotspots/issues for troubleshooting"
|
|
3955
|
-
).option(
|
|
3956
|
-
"--latency-threshold <ms>",
|
|
3957
|
-
`Latency threshold in ms for hotspot detection (default: ${DEFAULT_LATENCY_THRESHOLD})`,
|
|
3958
|
-
String(DEFAULT_LATENCY_THRESHOLD)
|
|
3959
|
-
).option(
|
|
3960
|
-
"--silence-threshold <ms>",
|
|
3961
|
-
`Silence threshold in ms for hotspot detection (default: ${DEFAULT_SILENCE_THRESHOLD})`,
|
|
3962
|
-
String(DEFAULT_SILENCE_THRESHOLD)
|
|
3963
|
-
).addHelpText(
|
|
3964
|
-
"after",
|
|
3965
|
-
`
|
|
3966
|
-
Examples:
|
|
3967
|
-
$ retell transcripts analyze call_abc123
|
|
3968
|
-
$ retell transcripts analyze call_abc123 --fields call_id,performance
|
|
3969
|
-
$ retell transcripts analyze call_abc123 --raw
|
|
3970
|
-
$ retell transcripts analyze call_abc123 --raw --fields call_id,transcript_object
|
|
3971
|
-
$ retell transcripts analyze call_abc123 --hotspots-only
|
|
3972
|
-
$ retell transcripts analyze call_abc123 --hotspots-only --latency-threshold 1500
|
|
3973
|
-
$ retell transcripts analyze call_abc123 --hotspots-only --fields hotspots
|
|
3974
|
-
$ retell transcripts analyze call_abc123 | jq '.performance.latency_p50_ms'
|
|
3975
|
-
`
|
|
3976
|
-
).action(async (callId, options) => {
|
|
3977
|
-
await analyzeTranscriptCommand(callId, {
|
|
3978
|
-
fields: options.fields,
|
|
3979
|
-
raw: options.raw,
|
|
3980
|
-
hotspotsOnly: options.hotspotsOnly,
|
|
3981
|
-
latencyThreshold: options.latencyThreshold ? parseInt(options.latencyThreshold) : void 0,
|
|
3982
|
-
silenceThreshold: options.silenceThreshold ? parseInt(options.silenceThreshold) : void 0
|
|
3983
|
-
});
|
|
3984
|
-
});
|
|
3985
|
-
transcripts.command("search").description("Search transcripts with advanced filtering").option("--status <status>", "Filter by call status (error, ended, ongoing)").option("--agent-id <id>", "Filter by agent ID").option(
|
|
3986
|
-
"--since <date>",
|
|
3987
|
-
"Filter calls after this date (YYYY-MM-DD or ISO format)"
|
|
3988
|
-
).option(
|
|
3989
|
-
"--until <date>",
|
|
3990
|
-
"Filter calls before this date (YYYY-MM-DD or ISO format)"
|
|
3991
|
-
).option("--limit <number>", "Maximum number of results (default: 50)", "50").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
3992
|
-
"after",
|
|
3993
|
-
`
|
|
3994
|
-
Examples:
|
|
3995
|
-
$ retell transcripts search --status error
|
|
3996
|
-
$ retell transcripts search --agent-id agent_123 --since 2025-11-01
|
|
3997
|
-
$ retell transcripts search --status error --limit 10
|
|
3998
|
-
$ retell transcripts search --status error --fields call_id,agent_id,call_status
|
|
3999
|
-
$ retell transcripts search --since 2025-11-01 --until 2025-11-15
|
|
4000
|
-
`
|
|
4001
|
-
).action(async (options) => {
|
|
4002
|
-
await searchTranscriptsCommand({
|
|
4003
|
-
status: options.status,
|
|
4004
|
-
agentId: options.agentId,
|
|
4005
|
-
since: options.since,
|
|
4006
|
-
until: options.until,
|
|
4007
|
-
limit: options.limit ? Number(options.limit) : void 0,
|
|
4008
|
-
fields: options.fields
|
|
4009
|
-
});
|
|
4010
|
-
});
|
|
4011
|
-
var agents = program.command("agents").description("Manage agents");
|
|
4012
|
-
agents.command("list").description("List all agents").option(
|
|
4013
|
-
"-l, --limit <number>",
|
|
4014
|
-
"Maximum number of agents to return (default: 100)",
|
|
4015
|
-
"100"
|
|
4016
|
-
).option(
|
|
4017
|
-
"--fields <fields>",
|
|
4018
|
-
"Comma-separated list of fields to return (e.g., agent_id,agent_name,response_engine_type)"
|
|
4019
|
-
).addHelpText(
|
|
4020
|
-
"after",
|
|
4021
|
-
`
|
|
4022
|
-
Examples:
|
|
4023
|
-
$ retell agents list
|
|
4024
|
-
$ retell agents list --limit 10
|
|
4025
|
-
$ retell agents list --fields agent_id,agent_name
|
|
4026
|
-
$ retell agents list | jq '.[] | select(.response_engine.type == "retell-llm")'
|
|
4027
|
-
`
|
|
4028
|
-
).action(async (options) => {
|
|
4029
|
-
const limit = parseInt(options.limit, 10);
|
|
4030
|
-
if (isNaN(limit) || limit < 1) {
|
|
4031
|
-
console.error("Error: limit must be a positive number");
|
|
4032
|
-
process.exit(1);
|
|
4004
|
+
const v = Number(value);
|
|
4005
|
+
if (!Number.isFinite(v)) {
|
|
4006
|
+
throwValidation3(`${flagName} must be a number`);
|
|
4033
4007
|
}
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
)
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4008
|
+
return v;
|
|
4009
|
+
}
|
|
4010
|
+
function throwValidation3(message) {
|
|
4011
|
+
const err = new Error(message);
|
|
4012
|
+
err.name = "ValidationError";
|
|
4013
|
+
throw err;
|
|
4014
|
+
}
|
|
4015
|
+
|
|
4016
|
+
// src/commands/phone-numbers/create.ts
|
|
4017
|
+
var VALID_COUNTRIES = ["US", "CA"];
|
|
4018
|
+
var VALID_PROVIDERS = ["twilio", "telnyx"];
|
|
4019
|
+
var VALID_TRANSPORTS = ["TLS", "TCP", "UDP"];
|
|
4020
|
+
async function createPhoneNumberCommand(options = {}) {
|
|
4021
|
+
try {
|
|
4022
|
+
if (options.countryCode && !VALID_COUNTRIES.includes(options.countryCode)) {
|
|
4023
|
+
throwValidation4(
|
|
4024
|
+
`--country-code must be one of: ${VALID_COUNTRIES.join(", ")}`
|
|
4025
|
+
);
|
|
4026
|
+
}
|
|
4027
|
+
if (options.numberProvider && !VALID_PROVIDERS.includes(options.numberProvider)) {
|
|
4028
|
+
throwValidation4(
|
|
4029
|
+
`--number-provider must be one of: ${VALID_PROVIDERS.join(", ")}`
|
|
4030
|
+
);
|
|
4031
|
+
}
|
|
4032
|
+
if (options.transport && !VALID_TRANSPORTS.includes(options.transport)) {
|
|
4033
|
+
throwValidation4(
|
|
4034
|
+
`--transport must be one of: ${VALID_TRANSPORTS.join(", ")}`
|
|
4035
|
+
);
|
|
4036
|
+
}
|
|
4037
|
+
const params = {};
|
|
4038
|
+
if (options.countryCode)
|
|
4039
|
+
params.country_code = options.countryCode;
|
|
4040
|
+
if (options.areaCode !== void 0) {
|
|
4041
|
+
params.area_code = parseNumericFlag(options.areaCode, "--area-code");
|
|
4042
|
+
}
|
|
4043
|
+
if (options.numberProvider)
|
|
4044
|
+
params.number_provider = options.numberProvider;
|
|
4045
|
+
if (options.tollFree !== void 0) params.toll_free = options.tollFree;
|
|
4046
|
+
if (options.nickname) params.nickname = options.nickname;
|
|
4047
|
+
if (options.phoneNumber) params.phone_number = options.phoneNumber;
|
|
4048
|
+
if (options.fallbackNumber) params.fallback_number = options.fallbackNumber;
|
|
4049
|
+
if (options.inboundWebhookUrl)
|
|
4050
|
+
params.inbound_webhook_url = options.inboundWebhookUrl;
|
|
4051
|
+
if (options.transport) params.transport = options.transport;
|
|
4052
|
+
if (options.allowedInboundCountryList)
|
|
4053
|
+
params.allowed_inbound_country_list = options.allowedInboundCountryList.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4054
|
+
if (options.allowedOutboundCountryList)
|
|
4055
|
+
params.allowed_outbound_country_list = options.allowedOutboundCountryList.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4056
|
+
applyWeightedAgents(
|
|
4057
|
+
params,
|
|
4058
|
+
{
|
|
4059
|
+
inboundAgent: options.inboundAgent,
|
|
4060
|
+
outboundAgent: options.outboundAgent,
|
|
4061
|
+
inboundAgents: options.inboundAgents,
|
|
4062
|
+
outboundAgents: options.outboundAgents,
|
|
4063
|
+
inboundSmsAgents: options.inboundSmsAgents,
|
|
4064
|
+
outboundSmsAgents: options.outboundSmsAgents
|
|
4065
|
+
},
|
|
4066
|
+
{ allowSms: false }
|
|
4067
|
+
);
|
|
4068
|
+
const client = getRetellClient();
|
|
4069
|
+
const pn = await client.phoneNumber.create(params);
|
|
4070
|
+
const output = options.fields ? filterFields(
|
|
4071
|
+
pn,
|
|
4072
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4073
|
+
) : pn;
|
|
4074
|
+
outputJson(output);
|
|
4075
|
+
} catch (error) {
|
|
4076
|
+
handleSdkError(error);
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
function throwValidation4(message) {
|
|
4080
|
+
const err = new Error(message);
|
|
4081
|
+
err.name = "ValidationError";
|
|
4082
|
+
throw err;
|
|
4083
|
+
}
|
|
4084
|
+
|
|
4085
|
+
// src/commands/phone-numbers/update.ts
|
|
4086
|
+
var VALID_TRANSPORTS2 = ["TLS", "TCP", "UDP"];
|
|
4087
|
+
async function updatePhoneNumberCommand(phoneNumber, options) {
|
|
4088
|
+
try {
|
|
4089
|
+
if (options.transport !== void 0 && options.transport !== "" && !VALID_TRANSPORTS2.includes(options.transport)) {
|
|
4090
|
+
throwValidation5(
|
|
4091
|
+
`--transport must be one of: ${VALID_TRANSPORTS2.join(", ")}`
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4094
|
+
const params = {};
|
|
4095
|
+
if (options.nickname !== void 0)
|
|
4096
|
+
params.nickname = options.nickname === "" ? null : options.nickname;
|
|
4097
|
+
if (options.terminationUri !== void 0)
|
|
4098
|
+
params.termination_uri = requireNonEmpty(
|
|
4099
|
+
options.terminationUri,
|
|
4100
|
+
"--termination-uri"
|
|
4101
|
+
);
|
|
4102
|
+
if (options.sipUsername !== void 0)
|
|
4103
|
+
params.auth_username = requireNonEmpty(
|
|
4104
|
+
options.sipUsername,
|
|
4105
|
+
"--sip-username"
|
|
4106
|
+
);
|
|
4107
|
+
if (options.sipPassword !== void 0)
|
|
4108
|
+
params.auth_password = requireNonEmpty(
|
|
4109
|
+
options.sipPassword,
|
|
4110
|
+
"--sip-password"
|
|
4111
|
+
);
|
|
4112
|
+
if (options.transport !== void 0)
|
|
4113
|
+
params.transport = options.transport === "" ? null : options.transport;
|
|
4114
|
+
if (options.inboundWebhookUrl !== void 0)
|
|
4115
|
+
params.inbound_webhook_url = options.inboundWebhookUrl === "" ? null : options.inboundWebhookUrl;
|
|
4116
|
+
if (options.inboundSmsWebhookUrl !== void 0)
|
|
4117
|
+
params.inbound_sms_webhook_url = options.inboundSmsWebhookUrl === "" ? null : options.inboundSmsWebhookUrl;
|
|
4118
|
+
if (options.fallbackNumber !== void 0)
|
|
4119
|
+
params.fallback_number = options.fallbackNumber === "" ? null : options.fallbackNumber;
|
|
4120
|
+
if (options.allowedInboundCountryList !== void 0)
|
|
4121
|
+
params.allowed_inbound_country_list = options.allowedInboundCountryList === "" ? null : options.allowedInboundCountryList.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4122
|
+
if (options.allowedOutboundCountryList !== void 0)
|
|
4123
|
+
params.allowed_outbound_country_list = options.allowedOutboundCountryList === "" ? null : options.allowedOutboundCountryList.split(",").map((s) => s.trim()).filter(Boolean);
|
|
4124
|
+
applyWeightedAgents(
|
|
4125
|
+
params,
|
|
4126
|
+
{
|
|
4127
|
+
inboundAgent: options.inboundAgent,
|
|
4128
|
+
outboundAgent: options.outboundAgent,
|
|
4129
|
+
inboundAgents: options.inboundAgents,
|
|
4130
|
+
outboundAgents: options.outboundAgents,
|
|
4131
|
+
inboundSmsAgents: options.inboundSmsAgents,
|
|
4132
|
+
outboundSmsAgents: options.outboundSmsAgents
|
|
4133
|
+
},
|
|
4134
|
+
{ allowSms: true }
|
|
4135
|
+
);
|
|
4136
|
+
if (Object.keys(params).length === 0) {
|
|
4137
|
+
throwValidation5(
|
|
4138
|
+
"No mutation flags provided. Pass at least one flag such as --nickname, --inbound-agent, --termination-uri, etc."
|
|
4139
|
+
);
|
|
4140
|
+
}
|
|
4141
|
+
const client = getRetellClient();
|
|
4142
|
+
const pn = await client.phoneNumber.update(phoneNumber, params);
|
|
4143
|
+
const output = options.fields ? filterFields(
|
|
4144
|
+
pn,
|
|
4145
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4146
|
+
) : pn;
|
|
4147
|
+
outputJson(output);
|
|
4148
|
+
} catch (error) {
|
|
4149
|
+
handleSdkError(error);
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
function throwValidation5(message) {
|
|
4153
|
+
const err = new Error(message);
|
|
4154
|
+
err.name = "ValidationError";
|
|
4155
|
+
throw err;
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
// src/commands/phone-numbers/delete.ts
|
|
4159
|
+
async function deletePhoneNumberCommand(phoneNumber) {
|
|
4160
|
+
try {
|
|
4161
|
+
const client = getRetellClient();
|
|
4162
|
+
await client.phoneNumber.delete(phoneNumber);
|
|
4163
|
+
outputJson({
|
|
4164
|
+
message: "Phone number deleted successfully",
|
|
4165
|
+
phone_number: phoneNumber,
|
|
4166
|
+
operation: "delete"
|
|
4167
|
+
});
|
|
4168
|
+
} catch (error) {
|
|
4169
|
+
handleSdkError(error);
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
// src/services/json-arg.ts
|
|
4174
|
+
var import_fs17 = require("fs");
|
|
4175
|
+
function loadJsonArg(value, flagName) {
|
|
4176
|
+
if (value === void 0 || value === null || value === "") {
|
|
4177
|
+
return void 0;
|
|
4178
|
+
}
|
|
4179
|
+
if (value.startsWith("@")) {
|
|
4180
|
+
const path = value.slice(1);
|
|
4181
|
+
if (path === "") {
|
|
4182
|
+
throwValidation6(`${flagName}: empty path after @`);
|
|
4183
|
+
}
|
|
4184
|
+
if (!(0, import_fs17.existsSync)(path)) {
|
|
4185
|
+
throwValidation6(`${flagName}: file not found: ${path}`);
|
|
4186
|
+
}
|
|
4187
|
+
let content;
|
|
4188
|
+
try {
|
|
4189
|
+
content = (0, import_fs17.readFileSync)(path, "utf-8");
|
|
4190
|
+
} catch (err) {
|
|
4191
|
+
throwValidation6(
|
|
4192
|
+
`${flagName}: failed to read ${path}: ${err.message}`
|
|
4193
|
+
);
|
|
4194
|
+
}
|
|
4195
|
+
try {
|
|
4196
|
+
return JSON.parse(content);
|
|
4197
|
+
} catch (err) {
|
|
4198
|
+
throwValidation6(
|
|
4199
|
+
`${flagName}: invalid JSON in ${path}: ${err.message}`
|
|
4200
|
+
);
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
try {
|
|
4204
|
+
return JSON.parse(value);
|
|
4205
|
+
} catch (err) {
|
|
4206
|
+
throwValidation6(`${flagName}: invalid JSON: ${err.message}`);
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
function readJsonFile(path, flagName) {
|
|
4210
|
+
if (!(0, import_fs17.existsSync)(path)) {
|
|
4211
|
+
throwValidation6(`${flagName}: file not found: ${path}`);
|
|
4212
|
+
}
|
|
4213
|
+
let content;
|
|
4214
|
+
try {
|
|
4215
|
+
content = (0, import_fs17.readFileSync)(path, "utf-8");
|
|
4216
|
+
} catch (err) {
|
|
4217
|
+
throwValidation6(
|
|
4218
|
+
`${flagName}: failed to read ${path}: ${err.message}`
|
|
4219
|
+
);
|
|
4220
|
+
}
|
|
4221
|
+
try {
|
|
4222
|
+
return JSON.parse(content);
|
|
4223
|
+
} catch (err) {
|
|
4224
|
+
throwValidation6(
|
|
4225
|
+
`${flagName}: invalid JSON in ${path}: ${err.message}`
|
|
4226
|
+
);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
function readJsonObjectFile(path, flagName) {
|
|
4230
|
+
const parsed = readJsonFile(path, flagName);
|
|
4231
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4232
|
+
throwValidation6(
|
|
4233
|
+
`${flagName}: ${path} must contain a JSON object, not ${jsonKind(parsed)}`
|
|
4234
|
+
);
|
|
4235
|
+
}
|
|
4236
|
+
return parsed;
|
|
4237
|
+
}
|
|
4238
|
+
function jsonKind(value) {
|
|
4239
|
+
if (value === null) return "null";
|
|
4240
|
+
if (Array.isArray(value)) return "an array";
|
|
4241
|
+
return `a ${typeof value}`;
|
|
4242
|
+
}
|
|
4243
|
+
function throwValidation6(message) {
|
|
4244
|
+
const err = new Error(message);
|
|
4245
|
+
err.name = "ValidationError";
|
|
4246
|
+
throw err;
|
|
4247
|
+
}
|
|
4248
|
+
|
|
4249
|
+
// src/commands/calls/create-phone.ts
|
|
4250
|
+
async function createPhoneCallCommand(options) {
|
|
4251
|
+
try {
|
|
4252
|
+
const params = {
|
|
4253
|
+
from_number: requireNonEmpty(options.fromNumber, "--from-number"),
|
|
4254
|
+
to_number: requireNonEmpty(options.toNumber, "--to-number")
|
|
4255
|
+
};
|
|
4256
|
+
if (options.overrideAgentId)
|
|
4257
|
+
params.override_agent_id = options.overrideAgentId;
|
|
4258
|
+
if (options.overrideAgentVersion !== void 0) {
|
|
4259
|
+
params.override_agent_version = parseNumericFlag(
|
|
4260
|
+
options.overrideAgentVersion,
|
|
4261
|
+
"--override-agent-version"
|
|
4262
|
+
);
|
|
4263
|
+
}
|
|
4264
|
+
if (options.ignoreE164Validation) params.ignore_e164_validation = true;
|
|
4265
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4266
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4267
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4268
|
+
if (dv !== void 0)
|
|
4269
|
+
params.retell_llm_dynamic_variables = dv;
|
|
4270
|
+
const headers = loadJsonArg(
|
|
4271
|
+
options.customSipHeaders,
|
|
4272
|
+
"--custom-sip-headers"
|
|
4273
|
+
);
|
|
4274
|
+
if (headers !== void 0)
|
|
4275
|
+
params.custom_sip_headers = headers;
|
|
4276
|
+
if (options.agentOverride) {
|
|
4277
|
+
const override = readJsonObjectFile(
|
|
4278
|
+
options.agentOverride,
|
|
4279
|
+
"--agent-override"
|
|
4280
|
+
);
|
|
4281
|
+
params.agent_override = override;
|
|
4282
|
+
}
|
|
4283
|
+
const client = getRetellClient();
|
|
4284
|
+
const result = await client.call.createPhoneCall(params);
|
|
4285
|
+
const output = options.fields ? filterFields(
|
|
4286
|
+
result,
|
|
4287
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4288
|
+
) : result;
|
|
4289
|
+
outputJson(output);
|
|
4290
|
+
} catch (error) {
|
|
4291
|
+
handleSdkError(error);
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
// src/commands/calls/create-web.ts
|
|
4296
|
+
async function createWebCallCommand(options) {
|
|
4297
|
+
try {
|
|
4298
|
+
const params = {
|
|
4299
|
+
agent_id: requireNonEmpty(options.agentId, "--agent-id")
|
|
4300
|
+
};
|
|
4301
|
+
if (options.agentVersion !== void 0) {
|
|
4302
|
+
params.agent_version = parseNumericFlag(
|
|
4303
|
+
options.agentVersion,
|
|
4304
|
+
"--agent-version"
|
|
4305
|
+
);
|
|
4306
|
+
}
|
|
4307
|
+
if (options.currentNodeId !== void 0)
|
|
4308
|
+
params.current_node_id = options.currentNodeId;
|
|
4309
|
+
if (options.currentState !== void 0)
|
|
4310
|
+
params.current_state = options.currentState;
|
|
4311
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4312
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4313
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4314
|
+
if (dv !== void 0)
|
|
4315
|
+
params.retell_llm_dynamic_variables = dv;
|
|
4316
|
+
if (options.agentOverride) {
|
|
4317
|
+
const override = readJsonObjectFile(
|
|
4318
|
+
options.agentOverride,
|
|
4319
|
+
"--agent-override"
|
|
4320
|
+
);
|
|
4321
|
+
params.agent_override = override;
|
|
4322
|
+
}
|
|
4323
|
+
const client = getRetellClient();
|
|
4324
|
+
const result = await client.call.createWebCall(params);
|
|
4325
|
+
const output = options.fields ? filterFields(
|
|
4326
|
+
result,
|
|
4327
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4328
|
+
) : result;
|
|
4329
|
+
outputJson(output);
|
|
4330
|
+
} catch (error) {
|
|
4331
|
+
handleSdkError(error);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4335
|
+
// src/commands/calls/register-phone.ts
|
|
4336
|
+
async function registerPhoneCallCommand(options) {
|
|
4337
|
+
try {
|
|
4338
|
+
if (options.direction && !["inbound", "outbound"].includes(options.direction)) {
|
|
4339
|
+
throwValidation7("--direction must be 'inbound' or 'outbound'");
|
|
4340
|
+
}
|
|
4341
|
+
const params = {
|
|
4342
|
+
agent_id: requireNonEmpty(options.agentId, "--agent-id")
|
|
4343
|
+
};
|
|
4344
|
+
if (options.agentVersion !== void 0) {
|
|
4345
|
+
params.agent_version = parseNumericFlag(
|
|
4346
|
+
options.agentVersion,
|
|
4347
|
+
"--agent-version"
|
|
4348
|
+
);
|
|
4349
|
+
}
|
|
4350
|
+
if (options.direction)
|
|
4351
|
+
params.direction = options.direction;
|
|
4352
|
+
if (options.fromNumber !== void 0) {
|
|
4353
|
+
params.from_number = requireNonEmpty(options.fromNumber, "--from-number");
|
|
4354
|
+
}
|
|
4355
|
+
if (options.toNumber !== void 0) {
|
|
4356
|
+
params.to_number = requireNonEmpty(options.toNumber, "--to-number");
|
|
4357
|
+
}
|
|
4358
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4359
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4360
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4361
|
+
if (dv !== void 0)
|
|
4362
|
+
params.retell_llm_dynamic_variables = dv;
|
|
4363
|
+
const client = getRetellClient();
|
|
4364
|
+
const result = await client.call.registerPhoneCall(params);
|
|
4365
|
+
const output = options.fields ? filterFields(
|
|
4366
|
+
result,
|
|
4367
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4368
|
+
) : result;
|
|
4369
|
+
outputJson(output);
|
|
4370
|
+
} catch (error) {
|
|
4371
|
+
handleSdkError(error);
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
function throwValidation7(message) {
|
|
4375
|
+
const err = new Error(message);
|
|
4376
|
+
err.name = "ValidationError";
|
|
4377
|
+
throw err;
|
|
4378
|
+
}
|
|
4379
|
+
|
|
4380
|
+
// src/commands/calls/update.ts
|
|
4381
|
+
var DATA_STORAGE_SETTINGS = [
|
|
4382
|
+
"everything",
|
|
4383
|
+
"everything_except_pii",
|
|
4384
|
+
"basic_attributes_only"
|
|
4385
|
+
];
|
|
4386
|
+
async function updateCallCommand(callId, options) {
|
|
4387
|
+
try {
|
|
4388
|
+
const params = {};
|
|
4389
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4390
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4391
|
+
const attrs = loadJsonArg(options.customAttributes, "--custom-attributes");
|
|
4392
|
+
if (attrs !== void 0)
|
|
4393
|
+
params.custom_attributes = attrs;
|
|
4394
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4395
|
+
if (dv !== void 0)
|
|
4396
|
+
params.override_dynamic_variables = dv;
|
|
4397
|
+
if (options.dataStorageSetting) {
|
|
4398
|
+
if (!DATA_STORAGE_SETTINGS.includes(options.dataStorageSetting)) {
|
|
4399
|
+
throwValidation8(
|
|
4400
|
+
`--data-storage-setting must be one of: ${DATA_STORAGE_SETTINGS.join(", ")}`
|
|
4401
|
+
);
|
|
4402
|
+
}
|
|
4403
|
+
params.data_storage_setting = options.dataStorageSetting;
|
|
4404
|
+
}
|
|
4405
|
+
if (Object.keys(params).length === 0) {
|
|
4406
|
+
throwValidation8(
|
|
4407
|
+
"No mutation flags provided. Pass at least one of --metadata, --custom-attributes, --dynamic-variables, --data-storage-setting."
|
|
4408
|
+
);
|
|
4409
|
+
}
|
|
4410
|
+
const client = getRetellClient();
|
|
4411
|
+
const result = await client.call.update(callId, params);
|
|
4412
|
+
const output = options.fields ? filterFields(
|
|
4413
|
+
result,
|
|
4414
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4415
|
+
) : result;
|
|
4416
|
+
outputJson(output);
|
|
4417
|
+
} catch (error) {
|
|
4418
|
+
handleSdkError(error);
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
function throwValidation8(message) {
|
|
4422
|
+
const err = new Error(message);
|
|
4423
|
+
err.name = "ValidationError";
|
|
4424
|
+
throw err;
|
|
4425
|
+
}
|
|
4426
|
+
|
|
4427
|
+
// src/commands/calls/delete.ts
|
|
4428
|
+
async function deleteCallCommand(callId) {
|
|
4429
|
+
try {
|
|
4430
|
+
const client = getRetellClient();
|
|
4431
|
+
await client.call.delete(callId);
|
|
4432
|
+
outputJson({
|
|
4433
|
+
message: "Call deleted successfully",
|
|
4434
|
+
call_id: callId,
|
|
4435
|
+
operation: "delete"
|
|
4436
|
+
});
|
|
4437
|
+
} catch (error) {
|
|
4438
|
+
handleSdkError(error);
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
// src/commands/batch-calls/create.ts
|
|
4443
|
+
async function createBatchCallCommand(options) {
|
|
4444
|
+
try {
|
|
4445
|
+
const tasks = readJsonFile(options.tasks, "--tasks");
|
|
4446
|
+
if (!Array.isArray(tasks)) {
|
|
4447
|
+
throwValidation9("--tasks file must contain a JSON array of task objects");
|
|
4448
|
+
}
|
|
4449
|
+
const params = {
|
|
4450
|
+
from_number: requireNonEmpty(options.fromNumber, "--from-number"),
|
|
4451
|
+
tasks
|
|
4452
|
+
};
|
|
4453
|
+
if (options.name) params.name = options.name;
|
|
4454
|
+
if (options.reservedConcurrency !== void 0) {
|
|
4455
|
+
params.reserved_concurrency = parseNumericFlag(
|
|
4456
|
+
options.reservedConcurrency,
|
|
4457
|
+
"--reserved-concurrency"
|
|
4458
|
+
);
|
|
4459
|
+
}
|
|
4460
|
+
if (options.triggerTimestamp !== void 0) {
|
|
4461
|
+
params.trigger_timestamp = parseNumericFlag(
|
|
4462
|
+
options.triggerTimestamp,
|
|
4463
|
+
"--trigger-timestamp"
|
|
4464
|
+
);
|
|
4465
|
+
}
|
|
4466
|
+
if (options.callTimeWindow) {
|
|
4467
|
+
const window = readJsonObjectFile(
|
|
4468
|
+
options.callTimeWindow,
|
|
4469
|
+
"--call-time-window"
|
|
4470
|
+
);
|
|
4471
|
+
params.call_time_window = window;
|
|
4472
|
+
}
|
|
4473
|
+
const client = getRetellClient();
|
|
4474
|
+
const result = await client.batchCall.createBatchCall(params);
|
|
4475
|
+
const output = options.fields ? filterFields(
|
|
4476
|
+
result,
|
|
4477
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4478
|
+
) : result;
|
|
4479
|
+
outputJson(output);
|
|
4480
|
+
} catch (error) {
|
|
4481
|
+
handleSdkError(error);
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
function throwValidation9(message) {
|
|
4485
|
+
const err = new Error(message);
|
|
4486
|
+
err.name = "ValidationError";
|
|
4487
|
+
throw err;
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4490
|
+
// src/commands/llms/list.ts
|
|
4491
|
+
async function listLlmsCommand(options = {}) {
|
|
4492
|
+
try {
|
|
4493
|
+
const query = {};
|
|
4494
|
+
if (options.limit !== void 0) {
|
|
4495
|
+
query.limit = parseNumericFlag(options.limit, "--limit");
|
|
4496
|
+
}
|
|
4497
|
+
if (options.paginationKey) query.pagination_key = options.paginationKey;
|
|
4498
|
+
if (options.paginationKeyVersion !== void 0) {
|
|
4499
|
+
query.pagination_key_version = parseNumericFlag(
|
|
4500
|
+
options.paginationKeyVersion,
|
|
4501
|
+
"--pagination-key-version"
|
|
4502
|
+
);
|
|
4503
|
+
}
|
|
4504
|
+
const client = getRetellClient();
|
|
4505
|
+
const llms2 = await client.llm.list(query);
|
|
4506
|
+
const output = options.fields ? filterFields(
|
|
4507
|
+
llms2,
|
|
4508
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4509
|
+
) : llms2;
|
|
4510
|
+
outputJson(output);
|
|
4511
|
+
} catch (error) {
|
|
4512
|
+
handleSdkError(error);
|
|
4513
|
+
}
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4516
|
+
// src/commands/llms/get.ts
|
|
4517
|
+
async function getLlmCommand(llmId, options = {}) {
|
|
4518
|
+
try {
|
|
4519
|
+
const query = {};
|
|
4520
|
+
if (options.version !== void 0) {
|
|
4521
|
+
query.version = parseNumericFlag(options.version, "--version");
|
|
4522
|
+
}
|
|
4523
|
+
const client = getRetellClient();
|
|
4524
|
+
const llm = await client.llm.retrieve(llmId, query);
|
|
4525
|
+
const output = options.fields ? filterFields(
|
|
4526
|
+
llm,
|
|
4527
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4528
|
+
) : llm;
|
|
4529
|
+
outputJson(output);
|
|
4530
|
+
} catch (error) {
|
|
4531
|
+
handleSdkError(error);
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
|
|
4535
|
+
// src/commands/llms/create.ts
|
|
4536
|
+
async function createLlmCommand(options = {}) {
|
|
4537
|
+
try {
|
|
4538
|
+
let params;
|
|
4539
|
+
if (options.file) {
|
|
4540
|
+
const simpleFlags = [
|
|
4541
|
+
options.generalPrompt !== void 0 && "--general-prompt",
|
|
4542
|
+
options.model !== void 0 && "--model",
|
|
4543
|
+
options.s2sModel !== void 0 && "--s2s-model",
|
|
4544
|
+
options.startSpeaker !== void 0 && "--start-speaker",
|
|
4545
|
+
options.beginMessage !== void 0 && "--begin-message"
|
|
4546
|
+
].filter(Boolean);
|
|
4547
|
+
if (simpleFlags.length > 0) {
|
|
4548
|
+
throwValidation10(
|
|
4549
|
+
`--file is mutually exclusive with ${simpleFlags.join(", ")}. Put all fields in the JSON body.`
|
|
4550
|
+
);
|
|
4551
|
+
}
|
|
4552
|
+
params = readJsonObjectFile(
|
|
4553
|
+
options.file,
|
|
4554
|
+
"--file"
|
|
4555
|
+
);
|
|
4556
|
+
} else {
|
|
4557
|
+
params = {};
|
|
4558
|
+
if (options.generalPrompt !== void 0)
|
|
4559
|
+
params.general_prompt = options.generalPrompt;
|
|
4560
|
+
if (options.model)
|
|
4561
|
+
params.model = options.model;
|
|
4562
|
+
if (options.s2sModel)
|
|
4563
|
+
params.s2s_model = options.s2sModel;
|
|
4564
|
+
if (options.startSpeaker) {
|
|
4565
|
+
if (!["user", "agent"].includes(options.startSpeaker))
|
|
4566
|
+
throwValidation10("--start-speaker must be 'user' or 'agent'");
|
|
4567
|
+
params.start_speaker = options.startSpeaker;
|
|
4568
|
+
}
|
|
4569
|
+
if (options.beginMessage !== void 0)
|
|
4570
|
+
params.begin_message = options.beginMessage;
|
|
4571
|
+
}
|
|
4572
|
+
const client = getRetellClient();
|
|
4573
|
+
const llm = await client.llm.create(params);
|
|
4574
|
+
const output = options.fields ? filterFields(
|
|
4575
|
+
llm,
|
|
4576
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4577
|
+
) : llm;
|
|
4578
|
+
outputJson(output);
|
|
4579
|
+
} catch (error) {
|
|
4580
|
+
handleSdkError(error);
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
function throwValidation10(message) {
|
|
4584
|
+
const err = new Error(message);
|
|
4585
|
+
err.name = "ValidationError";
|
|
4586
|
+
throw err;
|
|
4587
|
+
}
|
|
4588
|
+
|
|
4589
|
+
// src/commands/llms/update.ts
|
|
4590
|
+
async function updateLlmCommand(llmId, options) {
|
|
4591
|
+
try {
|
|
4592
|
+
const rawBody = readJsonObjectFile(options.file, "--file");
|
|
4593
|
+
if (Object.keys(rawBody).length === 0) {
|
|
4594
|
+
const err = new Error(
|
|
4595
|
+
"--file body is empty. Pass at least one mutation field (e.g. general_prompt, model)."
|
|
4596
|
+
);
|
|
4597
|
+
err.name = "ValidationError";
|
|
4598
|
+
throw err;
|
|
4599
|
+
}
|
|
4600
|
+
const body = rawBody;
|
|
4601
|
+
if (options.version !== void 0) {
|
|
4602
|
+
body.query_version = parseNumericFlag(options.version, "--version");
|
|
4603
|
+
}
|
|
4604
|
+
const client = getRetellClient();
|
|
4605
|
+
const llm = await client.llm.update(llmId, body);
|
|
4606
|
+
const output = options.fields ? filterFields(
|
|
4607
|
+
llm,
|
|
4608
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4609
|
+
) : llm;
|
|
4610
|
+
outputJson(output);
|
|
4611
|
+
} catch (error) {
|
|
4612
|
+
handleSdkError(error);
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
|
|
4616
|
+
// src/commands/llms/delete.ts
|
|
4617
|
+
async function deleteLlmCommand(llmId) {
|
|
4618
|
+
try {
|
|
4619
|
+
const client = getRetellClient();
|
|
4620
|
+
await client.llm.delete(llmId);
|
|
4621
|
+
outputJson({
|
|
4622
|
+
message: "LLM deleted successfully",
|
|
4623
|
+
llm_id: llmId,
|
|
4624
|
+
operation: "delete"
|
|
4625
|
+
});
|
|
4626
|
+
} catch (error) {
|
|
4627
|
+
handleSdkError(error);
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
// src/commands/voices/list.ts
|
|
4632
|
+
async function listVoicesCommand(options = {}) {
|
|
4633
|
+
try {
|
|
4634
|
+
const client = getRetellClient();
|
|
4635
|
+
const voices2 = await client.voice.list();
|
|
4636
|
+
const output = options.fields ? filterFields(
|
|
4637
|
+
voices2,
|
|
4638
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4639
|
+
) : voices2;
|
|
4640
|
+
outputJson(output);
|
|
4641
|
+
} catch (error) {
|
|
4642
|
+
handleSdkError(error);
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4646
|
+
// src/commands/voices/get.ts
|
|
4647
|
+
async function getVoiceCommand(voiceId, options = {}) {
|
|
4648
|
+
try {
|
|
4649
|
+
const client = getRetellClient();
|
|
4650
|
+
const voice = await client.voice.retrieve(voiceId);
|
|
4651
|
+
const output = options.fields ? filterFields(
|
|
4652
|
+
voice,
|
|
4653
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4654
|
+
) : voice;
|
|
4655
|
+
outputJson(output);
|
|
4656
|
+
} catch (error) {
|
|
4657
|
+
handleSdkError(error);
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
|
|
4661
|
+
// src/commands/voices/add-resource.ts
|
|
4662
|
+
var VALID_PROVIDERS2 = [
|
|
4663
|
+
"elevenlabs",
|
|
4664
|
+
"cartesia",
|
|
4665
|
+
"minimax",
|
|
4666
|
+
"fish_audio"
|
|
4667
|
+
];
|
|
4668
|
+
async function addVoiceResourceCommand(options) {
|
|
4669
|
+
try {
|
|
4670
|
+
if (options.voiceProvider && !VALID_PROVIDERS2.includes(options.voiceProvider)) {
|
|
4671
|
+
throwValidation11(
|
|
4672
|
+
`--voice-provider must be one of: ${VALID_PROVIDERS2.join(", ")}`
|
|
4673
|
+
);
|
|
4674
|
+
}
|
|
4675
|
+
const params = {
|
|
4676
|
+
provider_voice_id: requireNonEmpty(
|
|
4677
|
+
options.providerVoiceId,
|
|
4678
|
+
"--provider-voice-id"
|
|
4679
|
+
),
|
|
4680
|
+
voice_name: requireNonEmpty(options.voiceName, "--voice-name")
|
|
4681
|
+
};
|
|
4682
|
+
if (options.voiceProvider)
|
|
4683
|
+
params.voice_provider = options.voiceProvider;
|
|
4684
|
+
if (options.publicUserId) params.public_user_id = options.publicUserId;
|
|
4685
|
+
const client = getRetellClient();
|
|
4686
|
+
const voice = await client.voice.addResource(params);
|
|
4687
|
+
const output = options.fields ? filterFields(
|
|
4688
|
+
voice,
|
|
4689
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4690
|
+
) : voice;
|
|
4691
|
+
outputJson(output);
|
|
4692
|
+
} catch (error) {
|
|
4693
|
+
handleSdkError(error);
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
function throwValidation11(message) {
|
|
4697
|
+
const err = new Error(message);
|
|
4698
|
+
err.name = "ValidationError";
|
|
4699
|
+
throw err;
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4702
|
+
// src/commands/voices/clone.ts
|
|
4703
|
+
var import_fs18 = require("fs");
|
|
4704
|
+
var VALID_PROVIDERS3 = [
|
|
4705
|
+
"elevenlabs",
|
|
4706
|
+
"cartesia",
|
|
4707
|
+
"minimax",
|
|
4708
|
+
"fish_audio",
|
|
4709
|
+
"platform"
|
|
4710
|
+
];
|
|
4711
|
+
async function cloneVoiceCommand(options) {
|
|
4712
|
+
try {
|
|
4713
|
+
if (!VALID_PROVIDERS3.includes(options.voiceProvider)) {
|
|
4714
|
+
throwValidation12(
|
|
4715
|
+
`--voice-provider must be one of: ${VALID_PROVIDERS3.join(", ")}`
|
|
4716
|
+
);
|
|
4717
|
+
}
|
|
4718
|
+
const files = options.file ?? [];
|
|
4719
|
+
if (files.length === 0) {
|
|
4720
|
+
throwValidation12("at least one --file is required");
|
|
4721
|
+
}
|
|
4722
|
+
for (const path of files) {
|
|
4723
|
+
if (!(0, import_fs18.existsSync)(path)) {
|
|
4724
|
+
throwValidation12(`--file: not found: ${path}`);
|
|
4725
|
+
}
|
|
4726
|
+
}
|
|
4727
|
+
const params = {
|
|
4728
|
+
voice_name: requireNonEmpty(options.voiceName, "--voice-name"),
|
|
4729
|
+
voice_provider: options.voiceProvider,
|
|
4730
|
+
files: files.map((p) => (0, import_fs18.createReadStream)(p))
|
|
4731
|
+
};
|
|
4732
|
+
const client = getRetellClient();
|
|
4733
|
+
const voice = await client.voice.clone(params);
|
|
4734
|
+
const output = options.fields ? filterFields(
|
|
4735
|
+
voice,
|
|
4736
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4737
|
+
) : voice;
|
|
4738
|
+
outputJson(output);
|
|
4739
|
+
} catch (error) {
|
|
4740
|
+
handleSdkError(error);
|
|
4741
|
+
}
|
|
4742
|
+
}
|
|
4743
|
+
function throwValidation12(message) {
|
|
4744
|
+
const err = new Error(message);
|
|
4745
|
+
err.name = "ValidationError";
|
|
4746
|
+
throw err;
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4749
|
+
// src/commands/voices/search.ts
|
|
4750
|
+
var VALID_PROVIDERS4 = [
|
|
4751
|
+
"elevenlabs",
|
|
4752
|
+
"cartesia",
|
|
4753
|
+
"minimax",
|
|
4754
|
+
"fish_audio"
|
|
4755
|
+
];
|
|
4756
|
+
async function searchVoicesCommand(options) {
|
|
4757
|
+
try {
|
|
4758
|
+
if (options.voiceProvider && !VALID_PROVIDERS4.includes(options.voiceProvider)) {
|
|
4759
|
+
throwValidation13(
|
|
4760
|
+
`--voice-provider must be one of: ${VALID_PROVIDERS4.join(", ")}`
|
|
4761
|
+
);
|
|
4762
|
+
}
|
|
4763
|
+
const params = {
|
|
4764
|
+
search_query: requireNonEmpty(options.searchQuery, "--search-query")
|
|
4765
|
+
};
|
|
4766
|
+
if (options.voiceProvider) {
|
|
4767
|
+
params.voice_provider = options.voiceProvider;
|
|
4768
|
+
}
|
|
4769
|
+
const client = getRetellClient();
|
|
4770
|
+
const result = await client.voice.search(params);
|
|
4771
|
+
const output = options.fields ? filterFields(
|
|
4772
|
+
result,
|
|
4773
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4774
|
+
) : result;
|
|
4775
|
+
outputJson(output);
|
|
4776
|
+
} catch (error) {
|
|
4777
|
+
handleSdkError(error);
|
|
4778
|
+
}
|
|
4779
|
+
}
|
|
4780
|
+
function throwValidation13(message) {
|
|
4781
|
+
const err = new Error(message);
|
|
4782
|
+
err.name = "ValidationError";
|
|
4783
|
+
throw err;
|
|
4784
|
+
}
|
|
4785
|
+
|
|
4786
|
+
// src/commands/chats/create.ts
|
|
4787
|
+
async function createChatCommand(options) {
|
|
4788
|
+
try {
|
|
4789
|
+
const params = {
|
|
4790
|
+
agent_id: requireNonEmpty(options.agentId, "--agent-id")
|
|
4791
|
+
};
|
|
4792
|
+
if (options.agentVersion !== void 0) {
|
|
4793
|
+
params.agent_version = parseNumericFlag(
|
|
4794
|
+
options.agentVersion,
|
|
4795
|
+
"--agent-version"
|
|
4796
|
+
);
|
|
4797
|
+
}
|
|
4798
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4799
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4800
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4801
|
+
if (dv !== void 0)
|
|
4802
|
+
params.retell_llm_dynamic_variables = dv;
|
|
4803
|
+
const client = getRetellClient();
|
|
4804
|
+
const chat = await client.chat.create(params);
|
|
4805
|
+
const output = options.fields ? filterFields(
|
|
4806
|
+
chat,
|
|
4807
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4808
|
+
) : chat;
|
|
4809
|
+
outputJson(output);
|
|
4810
|
+
} catch (error) {
|
|
4811
|
+
handleSdkError(error);
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
|
|
4815
|
+
// src/commands/chats/get.ts
|
|
4816
|
+
async function getChatCommand(chatId, options = {}) {
|
|
4817
|
+
try {
|
|
4818
|
+
const client = getRetellClient();
|
|
4819
|
+
const chat = await client.chat.retrieve(chatId);
|
|
4820
|
+
const output = options.fields ? filterFields(
|
|
4821
|
+
chat,
|
|
4822
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4823
|
+
) : chat;
|
|
4824
|
+
outputJson(output);
|
|
4825
|
+
} catch (error) {
|
|
4826
|
+
handleSdkError(error);
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
// src/commands/chats/list.ts
|
|
4831
|
+
async function listChatsCommand(options = {}) {
|
|
4832
|
+
try {
|
|
4833
|
+
const query = {};
|
|
4834
|
+
if (options.limit !== void 0) {
|
|
4835
|
+
query.limit = parseNumericFlag(options.limit, "--limit");
|
|
4836
|
+
}
|
|
4837
|
+
if (options.paginationKey) query.pagination_key = options.paginationKey;
|
|
4838
|
+
if (options.sortOrder) {
|
|
4839
|
+
if (!["ascending", "descending"].includes(options.sortOrder))
|
|
4840
|
+
throwValidation14("--sort-order must be 'ascending' or 'descending'");
|
|
4841
|
+
query.sort_order = options.sortOrder;
|
|
4842
|
+
}
|
|
4843
|
+
const client = getRetellClient();
|
|
4844
|
+
const chats2 = await client.chat.list(query);
|
|
4845
|
+
const output = options.fields ? filterFields(
|
|
4846
|
+
chats2,
|
|
4847
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4848
|
+
) : chats2;
|
|
4849
|
+
outputJson(output);
|
|
4850
|
+
} catch (error) {
|
|
4851
|
+
handleSdkError(error);
|
|
4852
|
+
}
|
|
4853
|
+
}
|
|
4854
|
+
function throwValidation14(message) {
|
|
4855
|
+
const err = new Error(message);
|
|
4856
|
+
err.name = "ValidationError";
|
|
4857
|
+
throw err;
|
|
4858
|
+
}
|
|
4859
|
+
|
|
4860
|
+
// src/commands/chats/update.ts
|
|
4861
|
+
var DATA_STORAGE_SETTINGS2 = ["everything", "basic_attributes_only"];
|
|
4862
|
+
async function updateChatCommand(chatId, options) {
|
|
4863
|
+
try {
|
|
4864
|
+
const params = {};
|
|
4865
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4866
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4867
|
+
const attrs = loadJsonArg(options.customAttributes, "--custom-attributes");
|
|
4868
|
+
if (attrs !== void 0)
|
|
4869
|
+
params.custom_attributes = attrs;
|
|
4870
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4871
|
+
if (dv !== void 0)
|
|
4872
|
+
params.override_dynamic_variables = dv;
|
|
4873
|
+
if (options.dataStorageSetting) {
|
|
4874
|
+
if (!DATA_STORAGE_SETTINGS2.includes(options.dataStorageSetting)) {
|
|
4875
|
+
throwValidation15(
|
|
4876
|
+
`--data-storage-setting must be one of: ${DATA_STORAGE_SETTINGS2.join(", ")}`
|
|
4877
|
+
);
|
|
4878
|
+
}
|
|
4879
|
+
params.data_storage_setting = options.dataStorageSetting;
|
|
4880
|
+
}
|
|
4881
|
+
if (Object.keys(params).length === 0) {
|
|
4882
|
+
throwValidation15(
|
|
4883
|
+
"No mutation flags provided. Pass at least one of --metadata, --custom-attributes, --dynamic-variables, --data-storage-setting."
|
|
4884
|
+
);
|
|
4885
|
+
}
|
|
4886
|
+
const client = getRetellClient();
|
|
4887
|
+
const chat = await client.chat.update(chatId, params);
|
|
4888
|
+
const output = options.fields ? filterFields(
|
|
4889
|
+
chat,
|
|
4890
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4891
|
+
) : chat;
|
|
4892
|
+
outputJson(output);
|
|
4893
|
+
} catch (error) {
|
|
4894
|
+
handleSdkError(error);
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
function throwValidation15(message) {
|
|
4898
|
+
const err = new Error(message);
|
|
4899
|
+
err.name = "ValidationError";
|
|
4900
|
+
throw err;
|
|
4901
|
+
}
|
|
4902
|
+
|
|
4903
|
+
// src/commands/chats/complete.ts
|
|
4904
|
+
async function chatCompleteCommand(options) {
|
|
4905
|
+
try {
|
|
4906
|
+
const client = getRetellClient();
|
|
4907
|
+
const result = await client.chat.createChatCompletion({
|
|
4908
|
+
chat_id: requireNonEmpty(options.chatId, "--chat-id"),
|
|
4909
|
+
content: requireNonEmpty(options.content, "--content")
|
|
4910
|
+
});
|
|
4911
|
+
const output = options.fields ? filterFields(
|
|
4912
|
+
result,
|
|
4913
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4914
|
+
) : result;
|
|
4915
|
+
outputJson(output);
|
|
4916
|
+
} catch (error) {
|
|
4917
|
+
handleSdkError(error);
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
|
|
4921
|
+
// src/commands/chats/sms.ts
|
|
4922
|
+
async function createSmsChatCommand(options) {
|
|
4923
|
+
try {
|
|
4924
|
+
const params = {
|
|
4925
|
+
from_number: requireNonEmpty(options.fromNumber, "--from-number"),
|
|
4926
|
+
to_number: requireNonEmpty(options.toNumber, "--to-number")
|
|
4927
|
+
};
|
|
4928
|
+
if (options.overrideAgentId)
|
|
4929
|
+
params.override_agent_id = options.overrideAgentId;
|
|
4930
|
+
if (options.overrideAgentVersion !== void 0) {
|
|
4931
|
+
params.override_agent_version = parseNumericFlag(
|
|
4932
|
+
options.overrideAgentVersion,
|
|
4933
|
+
"--override-agent-version"
|
|
4934
|
+
);
|
|
4935
|
+
}
|
|
4936
|
+
const metadata = loadJsonArg(options.metadata, "--metadata");
|
|
4937
|
+
if (metadata !== void 0) params.metadata = metadata;
|
|
4938
|
+
const dv = loadJsonArg(options.dynamicVariables, "--dynamic-variables");
|
|
4939
|
+
if (dv !== void 0)
|
|
4940
|
+
params.retell_llm_dynamic_variables = dv;
|
|
4941
|
+
const client = getRetellClient();
|
|
4942
|
+
const chat = await client.chat.createSMSChat(params);
|
|
4943
|
+
const output = options.fields ? filterFields(
|
|
4944
|
+
chat,
|
|
4945
|
+
options.fields.split(",").map((f) => f.trim())
|
|
4946
|
+
) : chat;
|
|
4947
|
+
outputJson(output);
|
|
4948
|
+
} catch (error) {
|
|
4949
|
+
handleSdkError(error);
|
|
4950
|
+
}
|
|
4951
|
+
}
|
|
4952
|
+
|
|
4953
|
+
// src/commands/chats/end.ts
|
|
4954
|
+
async function endChatCommand(chatId) {
|
|
4955
|
+
try {
|
|
4956
|
+
const client = getRetellClient();
|
|
4957
|
+
await client.chat.end(chatId);
|
|
4958
|
+
outputJson({
|
|
4959
|
+
message: "Chat ended successfully",
|
|
4960
|
+
chat_id: chatId,
|
|
4961
|
+
operation: "end"
|
|
4962
|
+
});
|
|
4963
|
+
} catch (error) {
|
|
4964
|
+
handleSdkError(error);
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
|
|
4968
|
+
// src/commands/chat-agents/create.ts
|
|
4969
|
+
async function createChatAgentCommand(options = {}) {
|
|
4970
|
+
try {
|
|
4971
|
+
let params;
|
|
4972
|
+
if (options.file) {
|
|
4973
|
+
const simpleFlags = [
|
|
4974
|
+
options.name !== void 0 && "--name",
|
|
4975
|
+
options.llmId !== void 0 && "--llm-id",
|
|
4976
|
+
options.flowId !== void 0 && "--flow-id",
|
|
4977
|
+
options.customLlm !== void 0 && "--custom-llm"
|
|
4978
|
+
].filter(Boolean);
|
|
4979
|
+
if (simpleFlags.length > 0) {
|
|
4980
|
+
throwValidation16(
|
|
4981
|
+
`--file is mutually exclusive with ${simpleFlags.join(", ")}. Put all fields in the JSON body.`
|
|
4982
|
+
);
|
|
4983
|
+
}
|
|
4984
|
+
params = readJsonObjectFile(
|
|
4985
|
+
options.file,
|
|
4986
|
+
"--file"
|
|
4987
|
+
);
|
|
4988
|
+
} else {
|
|
4989
|
+
const engineCount = [
|
|
4990
|
+
options.llmId,
|
|
4991
|
+
options.flowId,
|
|
4992
|
+
options.customLlm
|
|
4993
|
+
].filter(Boolean).length;
|
|
4994
|
+
if (engineCount === 0) {
|
|
4995
|
+
throwValidation16(
|
|
4996
|
+
"Must specify one of: --llm-id, --flow-id, or --custom-llm (or use --file)"
|
|
4997
|
+
);
|
|
4998
|
+
}
|
|
4999
|
+
if (engineCount > 1) {
|
|
5000
|
+
throwValidation16(
|
|
5001
|
+
"Only one of --llm-id, --flow-id, or --custom-llm can be specified"
|
|
5002
|
+
);
|
|
5003
|
+
}
|
|
5004
|
+
let responseEngine;
|
|
5005
|
+
if (options.llmId) {
|
|
5006
|
+
responseEngine = { type: "retell-llm", llm_id: options.llmId };
|
|
5007
|
+
} else if (options.flowId) {
|
|
5008
|
+
responseEngine = {
|
|
5009
|
+
type: "conversation-flow",
|
|
5010
|
+
conversation_flow_id: options.flowId
|
|
5011
|
+
};
|
|
5012
|
+
} else {
|
|
5013
|
+
responseEngine = {
|
|
5014
|
+
type: "custom-llm",
|
|
5015
|
+
llm_websocket_url: options.customLlm
|
|
5016
|
+
};
|
|
5017
|
+
}
|
|
5018
|
+
params = { response_engine: responseEngine };
|
|
5019
|
+
if (options.name) params.agent_name = options.name;
|
|
5020
|
+
}
|
|
5021
|
+
const client = getRetellClient();
|
|
5022
|
+
const agent2 = await client.chatAgent.create(params);
|
|
5023
|
+
const output = options.fields ? filterFields(
|
|
5024
|
+
agent2,
|
|
5025
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5026
|
+
) : agent2;
|
|
5027
|
+
outputJson(output);
|
|
5028
|
+
} catch (error) {
|
|
5029
|
+
handleSdkError(error);
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
5032
|
+
function throwValidation16(message) {
|
|
5033
|
+
const err = new Error(message);
|
|
5034
|
+
err.name = "ValidationError";
|
|
5035
|
+
throw err;
|
|
5036
|
+
}
|
|
5037
|
+
|
|
5038
|
+
// src/commands/chat-agents/get.ts
|
|
5039
|
+
async function getChatAgentCommand(agentId, options = {}) {
|
|
5040
|
+
try {
|
|
5041
|
+
const query = {};
|
|
5042
|
+
if (options.version !== void 0) {
|
|
5043
|
+
query.version = parseNumericFlag(options.version, "--version");
|
|
5044
|
+
}
|
|
5045
|
+
const client = getRetellClient();
|
|
5046
|
+
const agent2 = await client.chatAgent.retrieve(agentId, query);
|
|
5047
|
+
const output = options.fields ? filterFields(
|
|
5048
|
+
agent2,
|
|
5049
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5050
|
+
) : agent2;
|
|
5051
|
+
outputJson(output);
|
|
5052
|
+
} catch (error) {
|
|
5053
|
+
handleSdkError(error);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5057
|
+
// src/commands/chat-agents/update.ts
|
|
5058
|
+
async function updateChatAgentCommand(agentId, options) {
|
|
5059
|
+
try {
|
|
5060
|
+
const rawBody = readJsonObjectFile(options.file, "--file");
|
|
5061
|
+
if (Object.keys(rawBody).length === 0) {
|
|
5062
|
+
const err = new Error(
|
|
5063
|
+
"--file body is empty. Pass at least one mutation field (e.g. agent_name, response_engine)."
|
|
5064
|
+
);
|
|
5065
|
+
err.name = "ValidationError";
|
|
5066
|
+
throw err;
|
|
5067
|
+
}
|
|
5068
|
+
const body = rawBody;
|
|
5069
|
+
const client = getRetellClient();
|
|
5070
|
+
const agent2 = await client.chatAgent.update(agentId, body);
|
|
5071
|
+
const output = options.fields ? filterFields(
|
|
5072
|
+
agent2,
|
|
5073
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5074
|
+
) : agent2;
|
|
5075
|
+
outputJson(output);
|
|
5076
|
+
} catch (error) {
|
|
5077
|
+
handleSdkError(error);
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
|
|
5081
|
+
// src/commands/chat-agents/list.ts
|
|
5082
|
+
async function listChatAgentsCommand(options = {}) {
|
|
5083
|
+
try {
|
|
5084
|
+
const query = {};
|
|
5085
|
+
if (options.limit !== void 0) {
|
|
5086
|
+
query.limit = parseNumericFlag(options.limit, "--limit");
|
|
5087
|
+
}
|
|
5088
|
+
if (options.paginationKey) query.pagination_key = options.paginationKey;
|
|
5089
|
+
if (options.paginationKeyVersion !== void 0) {
|
|
5090
|
+
query.pagination_key_version = parseNumericFlag(
|
|
5091
|
+
options.paginationKeyVersion,
|
|
5092
|
+
"--pagination-key-version"
|
|
5093
|
+
);
|
|
5094
|
+
}
|
|
5095
|
+
const client = getRetellClient();
|
|
5096
|
+
const agents2 = await client.chatAgent.list(query);
|
|
5097
|
+
const output = options.fields ? filterFields(
|
|
5098
|
+
agents2,
|
|
5099
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5100
|
+
) : agents2;
|
|
5101
|
+
outputJson(output);
|
|
5102
|
+
} catch (error) {
|
|
5103
|
+
handleSdkError(error);
|
|
5104
|
+
}
|
|
5105
|
+
}
|
|
5106
|
+
|
|
5107
|
+
// src/commands/chat-agents/delete.ts
|
|
5108
|
+
async function deleteChatAgentCommand(agentId) {
|
|
5109
|
+
try {
|
|
5110
|
+
const client = getRetellClient();
|
|
5111
|
+
await client.chatAgent.delete(agentId);
|
|
5112
|
+
outputJson({
|
|
5113
|
+
message: "Chat agent deleted successfully",
|
|
5114
|
+
agent_id: agentId,
|
|
5115
|
+
operation: "delete"
|
|
5116
|
+
});
|
|
5117
|
+
} catch (error) {
|
|
5118
|
+
handleSdkError(error);
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
|
|
5122
|
+
// src/commands/chat-agents/versions.ts
|
|
5123
|
+
async function chatAgentVersionsCommand(agentId, options = {}) {
|
|
5124
|
+
try {
|
|
5125
|
+
const client = getRetellClient();
|
|
5126
|
+
const versions = await client.chatAgent.getVersions(agentId);
|
|
5127
|
+
const output = options.fields ? filterFields(
|
|
5128
|
+
versions,
|
|
5129
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5130
|
+
) : versions;
|
|
5131
|
+
outputJson(output);
|
|
5132
|
+
} catch (error) {
|
|
5133
|
+
handleSdkError(error);
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
|
|
5137
|
+
// src/commands/chat-agents/publish.ts
|
|
5138
|
+
async function publishChatAgentCommand(agentId) {
|
|
5139
|
+
try {
|
|
5140
|
+
const client = getRetellClient();
|
|
5141
|
+
await client.chatAgent.publish(agentId);
|
|
5142
|
+
outputJson({
|
|
5143
|
+
message: "Chat agent published successfully",
|
|
5144
|
+
agent_id: agentId,
|
|
5145
|
+
operation: "publish"
|
|
5146
|
+
});
|
|
5147
|
+
} catch (error) {
|
|
5148
|
+
handleSdkError(error);
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
// src/commands/flow-components/list.ts
|
|
5153
|
+
async function listFlowComponentsCommand(options = {}) {
|
|
5154
|
+
try {
|
|
5155
|
+
const client = getRetellClient();
|
|
5156
|
+
const items = await client.conversationFlowComponent.list();
|
|
5157
|
+
const output = options.fields ? filterFields(
|
|
5158
|
+
items,
|
|
5159
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5160
|
+
) : items;
|
|
5161
|
+
outputJson(output);
|
|
5162
|
+
} catch (error) {
|
|
5163
|
+
handleSdkError(error);
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
|
|
5167
|
+
// src/commands/flow-components/get.ts
|
|
5168
|
+
async function getFlowComponentCommand(componentId, options = {}) {
|
|
5169
|
+
try {
|
|
5170
|
+
const client = getRetellClient();
|
|
5171
|
+
const component = await client.conversationFlowComponent.retrieve(componentId);
|
|
5172
|
+
const output = options.fields ? filterFields(
|
|
5173
|
+
component,
|
|
5174
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5175
|
+
) : component;
|
|
5176
|
+
outputJson(output);
|
|
5177
|
+
} catch (error) {
|
|
5178
|
+
handleSdkError(error);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
5181
|
+
|
|
5182
|
+
// src/commands/flow-components/create.ts
|
|
5183
|
+
async function createFlowComponentCommand(options) {
|
|
5184
|
+
try {
|
|
5185
|
+
const body = readJsonObjectFile(
|
|
5186
|
+
options.file,
|
|
5187
|
+
"--file"
|
|
5188
|
+
);
|
|
5189
|
+
const client = getRetellClient();
|
|
5190
|
+
const component = await client.conversationFlowComponent.create(body);
|
|
5191
|
+
const output = options.fields ? filterFields(
|
|
5192
|
+
component,
|
|
5193
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5194
|
+
) : component;
|
|
5195
|
+
outputJson(output);
|
|
5196
|
+
} catch (error) {
|
|
5197
|
+
handleSdkError(error);
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
|
|
5201
|
+
// src/commands/flow-components/update.ts
|
|
5202
|
+
async function updateFlowComponentCommand(componentId, options) {
|
|
5203
|
+
try {
|
|
5204
|
+
const rawBody = readJsonObjectFile(options.file, "--file");
|
|
5205
|
+
if (Object.keys(rawBody).length === 0) {
|
|
5206
|
+
const err = new Error(
|
|
5207
|
+
"--file body is empty. Pass at least one mutation field."
|
|
5208
|
+
);
|
|
5209
|
+
err.name = "ValidationError";
|
|
5210
|
+
throw err;
|
|
5211
|
+
}
|
|
5212
|
+
const body = rawBody;
|
|
5213
|
+
const client = getRetellClient();
|
|
5214
|
+
const component = await client.conversationFlowComponent.update(
|
|
5215
|
+
componentId,
|
|
5216
|
+
body
|
|
5217
|
+
);
|
|
5218
|
+
const output = options.fields ? filterFields(
|
|
5219
|
+
component,
|
|
5220
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5221
|
+
) : component;
|
|
5222
|
+
outputJson(output);
|
|
5223
|
+
} catch (error) {
|
|
5224
|
+
handleSdkError(error);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5228
|
+
// src/commands/flow-components/delete.ts
|
|
5229
|
+
async function deleteFlowComponentCommand(componentId) {
|
|
5230
|
+
try {
|
|
5231
|
+
const client = getRetellClient();
|
|
5232
|
+
await client.conversationFlowComponent.delete(componentId);
|
|
5233
|
+
outputJson({
|
|
5234
|
+
message: "Flow component deleted successfully",
|
|
5235
|
+
conversation_flow_component_id: componentId,
|
|
5236
|
+
operation: "delete"
|
|
5237
|
+
});
|
|
5238
|
+
} catch (error) {
|
|
5239
|
+
handleSdkError(error);
|
|
5240
|
+
}
|
|
5241
|
+
}
|
|
5242
|
+
|
|
5243
|
+
// src/commands/concurrency/get.ts
|
|
5244
|
+
async function getConcurrencyCommand(options = {}) {
|
|
5245
|
+
try {
|
|
5246
|
+
const client = getRetellClient();
|
|
5247
|
+
const result = await client.concurrency.retrieve();
|
|
5248
|
+
const output = options.fields ? filterFields(
|
|
5249
|
+
result,
|
|
5250
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5251
|
+
) : result;
|
|
5252
|
+
outputJson(output);
|
|
5253
|
+
} catch (error) {
|
|
5254
|
+
handleSdkError(error);
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
|
|
5258
|
+
// src/commands/agents/mcp-tools.ts
|
|
5259
|
+
async function agentMcpToolsCommand(agentId, options) {
|
|
5260
|
+
try {
|
|
5261
|
+
const query = {
|
|
5262
|
+
mcp_id: requireNonEmpty(options.mcpId, "--mcp-id")
|
|
5263
|
+
};
|
|
5264
|
+
if (options.componentId) query.component_id = options.componentId;
|
|
5265
|
+
if (options.version !== void 0) {
|
|
5266
|
+
query.version = parseNumericFlag(options.version, "--version");
|
|
5267
|
+
}
|
|
5268
|
+
const client = getRetellClient();
|
|
5269
|
+
const tools2 = await client.mcpTool.getMcpTools(agentId, query);
|
|
5270
|
+
const output = options.fields ? filterFields(
|
|
5271
|
+
tools2,
|
|
5272
|
+
options.fields.split(",").map((f) => f.trim())
|
|
5273
|
+
) : tools2;
|
|
5274
|
+
outputJson(output);
|
|
5275
|
+
} catch (error) {
|
|
5276
|
+
handleSdkError(error);
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
|
|
5280
|
+
// src/index.ts
|
|
5281
|
+
var packageJson = JSON.parse(
|
|
5282
|
+
(0, import_fs19.readFileSync)((0, import_path6.join)(__dirname, "../package.json"), "utf-8")
|
|
5283
|
+
);
|
|
5284
|
+
function parseFlagOrExit(value, flagName) {
|
|
5285
|
+
if (value === void 0) return void 0;
|
|
5286
|
+
try {
|
|
5287
|
+
return parseNumericFlag(value, flagName);
|
|
5288
|
+
} catch (err) {
|
|
5289
|
+
console.error(`Error: ${err.message}`);
|
|
5290
|
+
process.exit(1);
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
var program = new import_commander.Command();
|
|
5294
|
+
program.name("retell").description("Retell AI CLI - Manage transcripts and agent prompts").version(packageJson.version, "-v, --version", "Display version number").helpOption("-h, --help", "Display help for command").option("--json", "Output as JSON (default)", true);
|
|
5295
|
+
program.command("login").description("Authenticate with Retell AI").addHelpText(
|
|
5296
|
+
"after",
|
|
5297
|
+
`
|
|
5298
|
+
Examples:
|
|
5299
|
+
$ retell login
|
|
5300
|
+
# Enter your API key when prompted
|
|
5301
|
+
# Creates .retellrc.json in current directory
|
|
5302
|
+
`
|
|
5303
|
+
).action(async () => {
|
|
5304
|
+
await loginCommand();
|
|
5305
|
+
});
|
|
5306
|
+
var transcripts = program.command("transcripts").description("Manage call transcripts");
|
|
5307
|
+
transcripts.command("list").description("List all call transcripts").option(
|
|
5308
|
+
"-l, --limit <number>",
|
|
5309
|
+
"Maximum number of calls to return (default: 50)",
|
|
5310
|
+
"50"
|
|
5311
|
+
).option(
|
|
5312
|
+
"--fields <fields>",
|
|
5313
|
+
"Comma-separated list of fields to return (e.g., call_id,call_status,metadata.duration)"
|
|
5314
|
+
).addHelpText(
|
|
5315
|
+
"after",
|
|
5316
|
+
`
|
|
5317
|
+
Examples:
|
|
5318
|
+
$ retell transcripts list
|
|
5319
|
+
$ retell transcripts list --limit 100
|
|
5320
|
+
$ retell transcripts list --fields call_id,call_status
|
|
5321
|
+
$ retell transcripts list | jq '.[] | select(.call_status == "error")'
|
|
5322
|
+
`
|
|
5323
|
+
).action(async (options) => {
|
|
5324
|
+
const limit = parseFlagOrExit(options.limit, "--limit") ?? 50;
|
|
5325
|
+
if (limit < 1) {
|
|
5326
|
+
console.error("Error: --limit must be a positive number");
|
|
5327
|
+
process.exit(1);
|
|
5328
|
+
}
|
|
5329
|
+
await listTranscriptsCommand({
|
|
5330
|
+
limit,
|
|
5331
|
+
fields: options.fields
|
|
5332
|
+
});
|
|
5333
|
+
});
|
|
5334
|
+
transcripts.command("get <call_id>").description("Get a specific call transcript").option(
|
|
5335
|
+
"--fields <fields>",
|
|
5336
|
+
"Comma-separated list of fields to return (e.g., call_id,metadata.duration,analysis)"
|
|
5337
|
+
).addHelpText(
|
|
5338
|
+
"after",
|
|
5339
|
+
`
|
|
5340
|
+
Examples:
|
|
5341
|
+
$ retell transcripts get call_abc123
|
|
5342
|
+
$ retell transcripts get call_abc123 --fields call_id,metadata.duration
|
|
5343
|
+
$ retell transcripts get call_abc123 | jq '.transcript_object'
|
|
5344
|
+
`
|
|
5345
|
+
).action(async (callId, options) => {
|
|
5346
|
+
await getTranscriptCommand(callId, {
|
|
5347
|
+
fields: options.fields
|
|
5348
|
+
});
|
|
5349
|
+
});
|
|
5350
|
+
transcripts.command("analyze <call_id>").description(
|
|
5351
|
+
"Analyze a call transcript with performance metrics and insights"
|
|
5352
|
+
).option(
|
|
5353
|
+
"--fields <fields>",
|
|
5354
|
+
"Comma-separated list of fields to return (e.g., call_id,performance,analysis.summary)"
|
|
5355
|
+
).option(
|
|
5356
|
+
"--raw",
|
|
5357
|
+
"Return unmodified API response instead of enriched analysis"
|
|
5358
|
+
).option(
|
|
5359
|
+
"--hotspots-only",
|
|
5360
|
+
"Return only conversation hotspots/issues for troubleshooting"
|
|
5361
|
+
).option(
|
|
5362
|
+
"--latency-threshold <ms>",
|
|
5363
|
+
`Latency threshold in ms for hotspot detection (default: ${DEFAULT_LATENCY_THRESHOLD})`,
|
|
5364
|
+
String(DEFAULT_LATENCY_THRESHOLD)
|
|
5365
|
+
).option(
|
|
5366
|
+
"--silence-threshold <ms>",
|
|
5367
|
+
`Silence threshold in ms for hotspot detection (default: ${DEFAULT_SILENCE_THRESHOLD})`,
|
|
5368
|
+
String(DEFAULT_SILENCE_THRESHOLD)
|
|
5369
|
+
).addHelpText(
|
|
5370
|
+
"after",
|
|
5371
|
+
`
|
|
5372
|
+
Examples:
|
|
5373
|
+
$ retell transcripts analyze call_abc123
|
|
5374
|
+
$ retell transcripts analyze call_abc123 --fields call_id,performance
|
|
5375
|
+
$ retell transcripts analyze call_abc123 --raw
|
|
5376
|
+
$ retell transcripts analyze call_abc123 --raw --fields call_id,transcript_object
|
|
5377
|
+
$ retell transcripts analyze call_abc123 --hotspots-only
|
|
5378
|
+
$ retell transcripts analyze call_abc123 --hotspots-only --latency-threshold 1500
|
|
5379
|
+
$ retell transcripts analyze call_abc123 --hotspots-only --fields hotspots
|
|
5380
|
+
$ retell transcripts analyze call_abc123 | jq '.performance.latency_p50_ms'
|
|
5381
|
+
`
|
|
5382
|
+
).action(async (callId, options) => {
|
|
5383
|
+
await analyzeTranscriptCommand(callId, {
|
|
5384
|
+
fields: options.fields,
|
|
5385
|
+
raw: options.raw,
|
|
5386
|
+
hotspotsOnly: options.hotspotsOnly,
|
|
5387
|
+
latencyThreshold: parseFlagOrExit(
|
|
5388
|
+
options.latencyThreshold,
|
|
5389
|
+
"--latency-threshold"
|
|
5390
|
+
),
|
|
5391
|
+
silenceThreshold: parseFlagOrExit(
|
|
5392
|
+
options.silenceThreshold,
|
|
5393
|
+
"--silence-threshold"
|
|
5394
|
+
)
|
|
5395
|
+
});
|
|
5396
|
+
});
|
|
5397
|
+
transcripts.command("search").description("Search transcripts with advanced filtering").option("--status <status>", "Filter by call status (error, ended, ongoing)").option("--agent-id <id>", "Filter by agent ID").option(
|
|
5398
|
+
"--since <date>",
|
|
5399
|
+
"Filter calls after this date (YYYY-MM-DD or ISO format)"
|
|
5400
|
+
).option(
|
|
5401
|
+
"--until <date>",
|
|
5402
|
+
"Filter calls before this date (YYYY-MM-DD or ISO format)"
|
|
5403
|
+
).option("--limit <number>", "Maximum number of results (default: 50)", "50").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
5404
|
+
"after",
|
|
5405
|
+
`
|
|
5406
|
+
Examples:
|
|
5407
|
+
$ retell transcripts search --status error
|
|
5408
|
+
$ retell transcripts search --agent-id agent_123 --since 2025-11-01
|
|
5409
|
+
$ retell transcripts search --status error --limit 10
|
|
5410
|
+
$ retell transcripts search --status error --fields call_id,agent_id,call_status
|
|
5411
|
+
$ retell transcripts search --since 2025-11-01 --until 2025-11-15
|
|
5412
|
+
`
|
|
5413
|
+
).action(async (options) => {
|
|
5414
|
+
await searchTranscriptsCommand({
|
|
5415
|
+
status: options.status,
|
|
5416
|
+
agentId: options.agentId,
|
|
5417
|
+
since: options.since,
|
|
5418
|
+
until: options.until,
|
|
5419
|
+
limit: parseFlagOrExit(options.limit, "--limit"),
|
|
5420
|
+
fields: options.fields
|
|
5421
|
+
});
|
|
5422
|
+
});
|
|
5423
|
+
var agents = program.command("agents").description("Manage agents");
|
|
5424
|
+
agents.command("list").description("List all agents").option(
|
|
5425
|
+
"-l, --limit <number>",
|
|
5426
|
+
"Maximum number of agents to return (default: 100)",
|
|
5427
|
+
"100"
|
|
5428
|
+
).option(
|
|
5429
|
+
"--fields <fields>",
|
|
5430
|
+
"Comma-separated list of fields to return (e.g., agent_id,agent_name,response_engine_type)"
|
|
5431
|
+
).addHelpText(
|
|
5432
|
+
"after",
|
|
5433
|
+
`
|
|
5434
|
+
Examples:
|
|
5435
|
+
$ retell agents list
|
|
5436
|
+
$ retell agents list --limit 10
|
|
5437
|
+
$ retell agents list --fields agent_id,agent_name
|
|
5438
|
+
$ retell agents list | jq '.[] | select(.response_engine.type == "retell-llm")'
|
|
5439
|
+
`
|
|
5440
|
+
).action(async (options) => {
|
|
5441
|
+
const limit = parseFlagOrExit(options.limit, "--limit") ?? 50;
|
|
5442
|
+
if (limit < 1) {
|
|
5443
|
+
console.error("Error: --limit must be a positive number");
|
|
5444
|
+
process.exit(1);
|
|
5445
|
+
}
|
|
5446
|
+
await listAgentsCommand({
|
|
5447
|
+
limit,
|
|
5448
|
+
fields: options.fields
|
|
5449
|
+
});
|
|
5450
|
+
});
|
|
5451
|
+
agents.command("info <agent_id>").description("Get detailed agent information").option(
|
|
5452
|
+
"--fields <fields>",
|
|
5453
|
+
"Comma-separated list of fields to return (e.g., agent_name,response_engine.type,voice_config)"
|
|
5454
|
+
).addHelpText(
|
|
5455
|
+
"after",
|
|
5456
|
+
`
|
|
5457
|
+
Examples:
|
|
5458
|
+
$ retell agents info agent_123abc
|
|
5459
|
+
$ retell agents info agent_123abc --fields agent_name,response_engine.type
|
|
5460
|
+
$ retell agents info agent_123abc | jq '.response_engine.type'
|
|
5461
|
+
`
|
|
5462
|
+
).action(async (agentId, options) => {
|
|
5463
|
+
await agentInfoCommand(agentId, {
|
|
5464
|
+
fields: options.fields
|
|
5465
|
+
});
|
|
5466
|
+
});
|
|
5467
|
+
agents.command("create").description("Create a new agent").requiredOption("--voice <voice_id>", "Voice ID for the agent").option("--name <name>", "Agent name").option("--llm-id <id>", "Retell LLM ID (creates retell-llm response engine)").option(
|
|
5468
|
+
"--flow-id <id>",
|
|
5469
|
+
"Conversation Flow ID (creates conversation-flow response engine)"
|
|
5470
|
+
).option("--custom-llm <url>", "Custom LLM WebSocket URL").option(
|
|
5471
|
+
"-f, --file <path>",
|
|
5472
|
+
"Full agent config from JSON file (overrides other options)"
|
|
5473
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
5474
|
+
"after",
|
|
5475
|
+
`
|
|
5476
|
+
Examples:
|
|
5477
|
+
$ retell agents create --voice 11labs-Adrian --llm-id llm_xxx --name "Test Agent"
|
|
5478
|
+
$ retell agents create --voice 11labs-Adrian --flow-id cf_xxx
|
|
5479
|
+
$ retell agents create --file agent-config.json
|
|
5480
|
+
`
|
|
5481
|
+
).action(async (options) => {
|
|
5482
|
+
await createAgentCommand(options);
|
|
5483
|
+
});
|
|
5484
|
+
agents.command("delete <agent_id>").description("Delete an agent").addHelpText(
|
|
5485
|
+
"after",
|
|
5486
|
+
`
|
|
5487
|
+
Examples:
|
|
5488
|
+
$ retell agents delete agent_123abc
|
|
5489
|
+
`
|
|
5490
|
+
).action(async (agentId) => {
|
|
5491
|
+
await deleteAgentCommand(agentId);
|
|
5492
|
+
});
|
|
5493
|
+
agents.command("versions <agent_id>").description("List all versions of an agent").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
5494
|
+
"after",
|
|
5495
|
+
`
|
|
5496
|
+
Examples:
|
|
5497
|
+
$ retell agents versions agent_123abc
|
|
5498
|
+
$ retell agents versions agent_123abc --fields version,is_published
|
|
5499
|
+
`
|
|
5500
|
+
).action(async (agentId, options) => {
|
|
5501
|
+
await agentVersionsCommand(agentId, options);
|
|
5502
|
+
});
|
|
5503
|
+
var prompts = program.command("prompts").description("Manage agent prompts");
|
|
5504
|
+
prompts.command("pull <agent_id>").description("Download agent prompts to a local file").option(
|
|
5505
|
+
"-o, --output <path>",
|
|
5506
|
+
"Output file path (default: .retell-prompts/<agent_id>.json)",
|
|
5507
|
+
".retell-prompts"
|
|
5508
|
+
).addHelpText(
|
|
5509
|
+
"after",
|
|
5510
|
+
`
|
|
5511
|
+
Examples:
|
|
5512
|
+
$ retell prompts pull agent_123abc
|
|
5513
|
+
$ retell prompts pull agent_123abc --output my-prompts.json
|
|
5514
|
+
`
|
|
5515
|
+
).action(async (agentId, options) => {
|
|
5516
|
+
await pullPromptsCommand(agentId, options);
|
|
5517
|
+
});
|
|
5518
|
+
prompts.command("diff <agent_id>").description("Show differences between local and remote prompts").option(
|
|
5519
|
+
"-s, --source <path>",
|
|
5520
|
+
"Source directory path (default: .retell-prompts)",
|
|
5521
|
+
".retell-prompts"
|
|
5522
|
+
).option("-f, --fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
5523
|
+
"after",
|
|
4112
5524
|
`
|
|
4113
5525
|
Examples:
|
|
4114
5526
|
$ retell prompts diff agent_123abc
|
|
@@ -4163,7 +5575,7 @@ Examples:
|
|
|
4163
5575
|
`
|
|
4164
5576
|
).action(async (agentId, options) => {
|
|
4165
5577
|
await getAgentCommand(agentId, {
|
|
4166
|
-
version:
|
|
5578
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version"),
|
|
4167
5579
|
fields: options.fields
|
|
4168
5580
|
});
|
|
4169
5581
|
});
|
|
@@ -4202,7 +5614,7 @@ Note: Run 'retell agent-publish <agent_id>' after updating to publish changes.
|
|
|
4202
5614
|
await updateAgentCommand(agentId, {
|
|
4203
5615
|
file: options.file,
|
|
4204
5616
|
dryRun: options.dryRun,
|
|
4205
|
-
version:
|
|
5617
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version")
|
|
4206
5618
|
});
|
|
4207
5619
|
});
|
|
4208
5620
|
var tools = program.command("tools").description("Manage agent tools (custom functions, webhooks, etc.)");
|
|
@@ -4399,7 +5811,7 @@ Test case JSON format:
|
|
|
4399
5811
|
file: options.file,
|
|
4400
5812
|
llmId: options.llmId,
|
|
4401
5813
|
flowId: options.flowId,
|
|
4402
|
-
version:
|
|
5814
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version")
|
|
4403
5815
|
});
|
|
4404
5816
|
});
|
|
4405
5817
|
testsCases.command("update <test_case_definition_id>").description("Update an existing test case definition from a JSON file").requiredOption(
|
|
@@ -4477,7 +5889,7 @@ Examples:
|
|
|
4477
5889
|
llmId: options.llmId,
|
|
4478
5890
|
flowId: options.flowId,
|
|
4479
5891
|
cases: options.cases,
|
|
4480
|
-
version:
|
|
5892
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version")
|
|
4481
5893
|
});
|
|
4482
5894
|
});
|
|
4483
5895
|
var testsRuns = tests.command("runs").description("View test run results");
|
|
@@ -4609,10 +6021,10 @@ Examples:
|
|
|
4609
6021
|
$ retell flows list --fields conversation_flow_id,version,start_speaker
|
|
4610
6022
|
`
|
|
4611
6023
|
).action(async (options) => {
|
|
4612
|
-
const limit =
|
|
4613
|
-
if (
|
|
6024
|
+
const limit = parseFlagOrExit(options.limit, "--limit") ?? 50;
|
|
6025
|
+
if (limit < 1 || limit > 1e3) {
|
|
4614
6026
|
console.error(
|
|
4615
|
-
"Error: limit must be a positive number between 1 and 1000"
|
|
6027
|
+
"Error: --limit must be a positive number between 1 and 1000"
|
|
4616
6028
|
);
|
|
4617
6029
|
process.exit(1);
|
|
4618
6030
|
}
|
|
@@ -4634,7 +6046,7 @@ Examples:
|
|
|
4634
6046
|
`
|
|
4635
6047
|
).action(async (conversationFlowId, options) => {
|
|
4636
6048
|
await getFlowCommand(conversationFlowId, {
|
|
4637
|
-
version:
|
|
6049
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version"),
|
|
4638
6050
|
fields: options.fields
|
|
4639
6051
|
});
|
|
4640
6052
|
});
|
|
@@ -4676,7 +6088,7 @@ Examples:
|
|
|
4676
6088
|
).action(async (conversationFlowId, options) => {
|
|
4677
6089
|
await updateFlowCommand(conversationFlowId, {
|
|
4678
6090
|
file: options.file,
|
|
4679
|
-
version:
|
|
6091
|
+
version: parseFlagOrExit(options.engineVersion, "--engine-version")
|
|
4680
6092
|
});
|
|
4681
6093
|
});
|
|
4682
6094
|
flows.command("delete <conversation_flow_id>").description("Delete a conversation flow").addHelpText(
|
|
@@ -4694,7 +6106,7 @@ phoneNumbers.command("list").description("List all phone numbers").option("--fie
|
|
|
4694
6106
|
`
|
|
4695
6107
|
Examples:
|
|
4696
6108
|
$ retell phone-numbers list
|
|
4697
|
-
$ retell phone-numbers list --fields phone_number,nickname,
|
|
6109
|
+
$ retell phone-numbers list --fields phone_number,nickname,inbound_agents
|
|
4698
6110
|
`
|
|
4699
6111
|
).action(async (options) => {
|
|
4700
6112
|
await listPhoneNumbersCommand(options);
|
|
@@ -4704,22 +6116,353 @@ phoneNumbers.command("get <phone_number>").description("Get phone number details
|
|
|
4704
6116
|
`
|
|
4705
6117
|
Examples:
|
|
4706
6118
|
$ retell phone-numbers get +14157774444
|
|
4707
|
-
$ retell phone-numbers get +14157774444 --fields phone_number,
|
|
6119
|
+
$ retell phone-numbers get +14157774444 --fields phone_number,inbound_agents
|
|
4708
6120
|
`
|
|
4709
6121
|
).action(async (phoneNumber, options) => {
|
|
4710
6122
|
await getPhoneNumberCommand(phoneNumber, options);
|
|
4711
6123
|
});
|
|
4712
|
-
phoneNumbers.command("import").description("Import a phone number from custom telephony").requiredOption("--number <number>", "Phone number in E.164 format").requiredOption("--termination-uri <uri>", "SIP trunk termination URI").option("--nickname <name>", "Friendly name for reference").option(
|
|
6124
|
+
phoneNumbers.command("import").description("Import a phone number from custom telephony").requiredOption("--number <number>", "Phone number in E.164 format").requiredOption("--termination-uri <uri>", "SIP trunk termination URI").option("--nickname <name>", "Friendly name for reference").option(
|
|
6125
|
+
"--inbound-agent <id>",
|
|
6126
|
+
"Single agent for inbound calls (shorthand for weight 1)"
|
|
6127
|
+
).option(
|
|
6128
|
+
"--outbound-agent <id>",
|
|
6129
|
+
"Single agent for outbound calls (shorthand for weight 1)"
|
|
6130
|
+
).option(
|
|
6131
|
+
"--inbound-agents <spec>",
|
|
6132
|
+
"Weighted inbound agents (format: id:weight,id:weight)"
|
|
6133
|
+
).option(
|
|
6134
|
+
"--outbound-agents <spec>",
|
|
6135
|
+
"Weighted outbound agents (format: id:weight,id:weight)"
|
|
6136
|
+
).option("--sip-username <user>", "SIP trunk auth username").option("--sip-password <pass>", "SIP trunk auth password").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
4713
6137
|
"after",
|
|
4714
6138
|
`
|
|
4715
6139
|
Examples:
|
|
4716
6140
|
$ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com
|
|
4717
6141
|
$ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com --nickname "Support Line"
|
|
4718
6142
|
$ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com --inbound-agent agent_xxx
|
|
6143
|
+
$ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com --inbound-agents "agent_1:0.6,agent_2:0.4"
|
|
6144
|
+
|
|
6145
|
+
SMS agent bindings are not supported on import. Use \`phone-numbers update\` after import to bind SMS agents.
|
|
4719
6146
|
`
|
|
4720
6147
|
).action(async (options) => {
|
|
4721
6148
|
await importPhoneNumberCommand(options);
|
|
4722
6149
|
});
|
|
6150
|
+
phoneNumbers.command("create").description("Purchase a new phone number and bind agents").option("--country-code <code>", "Country code: US or CA").option("--area-code <code>", "3-digit US area code").option("--number-provider <provider>", "twilio or telnyx").option("--toll-free", "Purchase a toll-free number").option("--nickname <name>", "Friendly name for reference").option("--phone-number <number>", "Specific E.164 number to purchase").option(
|
|
6151
|
+
"--fallback-number <number>",
|
|
6152
|
+
"Enterprise: fallback destination during outage"
|
|
6153
|
+
).option("--inbound-webhook-url <url>", "Inbound call webhook URL").option("--transport <proto>", "SIP transport: TLS, TCP, or UDP").option(
|
|
6154
|
+
"--inbound-agent <id>",
|
|
6155
|
+
"Single inbound agent (shorthand for weight 1)"
|
|
6156
|
+
).option(
|
|
6157
|
+
"--outbound-agent <id>",
|
|
6158
|
+
"Single outbound agent (shorthand for weight 1)"
|
|
6159
|
+
).option(
|
|
6160
|
+
"--inbound-agents <spec>",
|
|
6161
|
+
"Weighted inbound agents (format: id:weight,id:weight)"
|
|
6162
|
+
).option(
|
|
6163
|
+
"--outbound-agents <spec>",
|
|
6164
|
+
"Weighted outbound agents (format: id:weight,id:weight)"
|
|
6165
|
+
).option(
|
|
6166
|
+
"--allowed-inbound-country-list <csv>",
|
|
6167
|
+
"Comma-separated ISO-2 country codes"
|
|
6168
|
+
).option(
|
|
6169
|
+
"--allowed-outbound-country-list <csv>",
|
|
6170
|
+
"Comma-separated ISO-2 country codes"
|
|
6171
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
6172
|
+
"after",
|
|
6173
|
+
`
|
|
6174
|
+
Examples:
|
|
6175
|
+
$ retell phone-numbers create --area-code 415 --nickname "Frontdesk"
|
|
6176
|
+
$ retell phone-numbers create --country-code US --toll-free --inbound-agent agent_xxx
|
|
6177
|
+
`
|
|
6178
|
+
).action(async (options) => {
|
|
6179
|
+
await createPhoneNumberCommand(options);
|
|
6180
|
+
});
|
|
6181
|
+
phoneNumbers.command("update <phone_number>").description("Update agents and settings bound to a phone number").option(
|
|
6182
|
+
"--nickname <name>",
|
|
6183
|
+
"Friendly name for reference (use empty string to clear)"
|
|
6184
|
+
).option(
|
|
6185
|
+
"--termination-uri <uri>",
|
|
6186
|
+
"SIP trunk termination URI (custom telephony)"
|
|
6187
|
+
).option("--sip-username <user>", "SIP trunk auth username").option("--sip-password <pass>", "SIP trunk auth password").option(
|
|
6188
|
+
"--transport <proto>",
|
|
6189
|
+
"SIP transport: TLS, TCP, or UDP (use empty string to clear)"
|
|
6190
|
+
).option(
|
|
6191
|
+
"--inbound-webhook-url <url>",
|
|
6192
|
+
"Inbound call webhook URL (use empty string to clear)"
|
|
6193
|
+
).option(
|
|
6194
|
+
"--inbound-sms-webhook-url <url>",
|
|
6195
|
+
"Inbound SMS webhook URL (use empty string to clear)"
|
|
6196
|
+
).option(
|
|
6197
|
+
"--fallback-number <number>",
|
|
6198
|
+
"Enterprise: fallback destination during outage (use empty string to clear)"
|
|
6199
|
+
).option(
|
|
6200
|
+
"--allowed-inbound-country-list <csv>",
|
|
6201
|
+
"Comma-separated ISO-2 country codes (use empty string to clear)"
|
|
6202
|
+
).option(
|
|
6203
|
+
"--allowed-outbound-country-list <csv>",
|
|
6204
|
+
"Comma-separated ISO-2 country codes (use empty string to clear)"
|
|
6205
|
+
).option(
|
|
6206
|
+
"--inbound-agent <id>",
|
|
6207
|
+
"Single inbound agent (shorthand for weight 1)"
|
|
6208
|
+
).option(
|
|
6209
|
+
"--outbound-agent <id>",
|
|
6210
|
+
"Single outbound agent (shorthand for weight 1)"
|
|
6211
|
+
).option(
|
|
6212
|
+
"--inbound-agents <spec>",
|
|
6213
|
+
"Weighted inbound agents (format: id:weight,id:weight)"
|
|
6214
|
+
).option(
|
|
6215
|
+
"--outbound-agents <spec>",
|
|
6216
|
+
"Weighted outbound agents (format: id:weight,id:weight)"
|
|
6217
|
+
).option("--inbound-sms-agents <spec>", "Weighted inbound SMS agents").option("--outbound-sms-agents <spec>", "Weighted outbound SMS agents").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
6218
|
+
"after",
|
|
6219
|
+
`
|
|
6220
|
+
Examples:
|
|
6221
|
+
$ retell phone-numbers update +14157774444 --inbound-agent agent_new
|
|
6222
|
+
$ retell phone-numbers update +14157774444 --inbound-agents "a:0.7,b:0.3" --nickname Support
|
|
6223
|
+
$ retell phone-numbers update +14157774444 --fallback-number "" (clear)
|
|
6224
|
+
`
|
|
6225
|
+
).action(async (phoneNumber, options) => {
|
|
6226
|
+
await updatePhoneNumberCommand(phoneNumber, options);
|
|
6227
|
+
});
|
|
6228
|
+
phoneNumbers.command("delete <phone_number>").description("Release an existing phone number").addHelpText(
|
|
6229
|
+
"after",
|
|
6230
|
+
`
|
|
6231
|
+
Examples:
|
|
6232
|
+
$ retell phone-numbers delete +14157774444
|
|
6233
|
+
`
|
|
6234
|
+
).action(async (phoneNumber) => {
|
|
6235
|
+
await deletePhoneNumberCommand(phoneNumber);
|
|
6236
|
+
});
|
|
6237
|
+
var calls = program.command("calls").description("Create and manage calls (list/get are under `transcripts`)");
|
|
6238
|
+
calls.command("create-phone").description("Create a new outbound phone call").requiredOption("--from-number <number>", "Caller number in E.164 format").requiredOption("--to-number <number>", "Callee number in E.164 format").option("--override-agent-id <id>", "One-time agent override for this call").option(
|
|
6239
|
+
"--override-agent-version <n>",
|
|
6240
|
+
"Override agent version for this call"
|
|
6241
|
+
).option("--metadata <json>", "Inline JSON or @path for call metadata").option(
|
|
6242
|
+
"--dynamic-variables <json>",
|
|
6243
|
+
"Inline JSON or @path for dynamic variables"
|
|
6244
|
+
).option(
|
|
6245
|
+
"--custom-sip-headers <json>",
|
|
6246
|
+
"Inline JSON or @path for custom SIP headers"
|
|
6247
|
+
).option(
|
|
6248
|
+
"--agent-override <path>",
|
|
6249
|
+
"Path to JSON file with agent_override block"
|
|
6250
|
+
).option(
|
|
6251
|
+
"--ignore-e164-validation",
|
|
6252
|
+
"Skip E.164 validation for from-number (custom telephony)"
|
|
6253
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
6254
|
+
"after",
|
|
6255
|
+
`
|
|
6256
|
+
Examples:
|
|
6257
|
+
$ retell calls create-phone --from-number +14157774444 --to-number +12137774445
|
|
6258
|
+
$ retell calls create-phone --from-number +1 --to-number +1 --metadata '{"customer_id":"c_1"}'
|
|
6259
|
+
`
|
|
6260
|
+
).action(async (options) => {
|
|
6261
|
+
await createPhoneCallCommand(options);
|
|
6262
|
+
});
|
|
6263
|
+
calls.command("create-web").description("Create a new web call for a browser-based agent").requiredOption("--agent-id <id>", "Agent to use for this web call").option("--agent-version <n>", "Specific agent version").option("--metadata <json>", "Inline JSON or @path for call metadata").option(
|
|
6264
|
+
"--dynamic-variables <json>",
|
|
6265
|
+
"Inline JSON or @path for dynamic variables"
|
|
6266
|
+
).option(
|
|
6267
|
+
"--agent-override <path>",
|
|
6268
|
+
"Path to JSON file with agent_override block"
|
|
6269
|
+
).option("--current-node-id <id>", "Start at this conversation-flow node").option("--current-state <name>", "Start at this Retell-LLM state").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6270
|
+
await createWebCallCommand(options);
|
|
6271
|
+
});
|
|
6272
|
+
calls.command("register-phone").description("Register a phone call for custom telephony (you dial)").requiredOption("--agent-id <id>", "Agent to use for this call").option("--agent-version <n>", "Specific agent version").option("--direction <dir>", "inbound or outbound").option("--from-number <n>", "Tracking from-number").option("--to-number <n>", "Tracking to-number").option("--metadata <json>", "Inline JSON or @path for call metadata").option(
|
|
6273
|
+
"--dynamic-variables <json>",
|
|
6274
|
+
"Inline JSON or @path for dynamic variables"
|
|
6275
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6276
|
+
await registerPhoneCallCommand(options);
|
|
6277
|
+
});
|
|
6278
|
+
calls.command("update <call_id>").description("Update metadata and storage settings on an existing call").option("--metadata <json>", "Inline JSON or @path for call metadata").option(
|
|
6279
|
+
"--custom-attributes <json>",
|
|
6280
|
+
"Inline JSON or @path for custom attributes"
|
|
6281
|
+
).option(
|
|
6282
|
+
"--dynamic-variables <json>",
|
|
6283
|
+
"Inline JSON or @path overriding dynamic variables"
|
|
6284
|
+
).option(
|
|
6285
|
+
"--data-storage-setting <value>",
|
|
6286
|
+
"everything | everything_except_pii | basic_attributes_only"
|
|
6287
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (callId, options) => {
|
|
6288
|
+
await updateCallCommand(callId, options);
|
|
6289
|
+
});
|
|
6290
|
+
calls.command("delete <call_id>").description("Delete a call and its associated data").action(async (callId) => {
|
|
6291
|
+
await deleteCallCommand(callId);
|
|
6292
|
+
});
|
|
6293
|
+
var batchCalls = program.command("batch-calls").description("Schedule bulk outbound calls");
|
|
6294
|
+
batchCalls.command("create").description("Create a new batch call").requiredOption("--from-number <number>", "Caller number in E.164 format").requiredOption(
|
|
6295
|
+
"--tasks <path>",
|
|
6296
|
+
"Path to JSON array of task objects ({to_number, ...})"
|
|
6297
|
+
).option("--name <name>", "Friendly name for your reference").option(
|
|
6298
|
+
"--reserved-concurrency <n>",
|
|
6299
|
+
"Concurrency reserved for non-batch calls"
|
|
6300
|
+
).option("--trigger-timestamp <ms>", "Scheduled send time (unix ms)").option(
|
|
6301
|
+
"--call-time-window <path>",
|
|
6302
|
+
"Path to JSON file with call_time_window object"
|
|
6303
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
6304
|
+
"after",
|
|
6305
|
+
`
|
|
6306
|
+
Examples:
|
|
6307
|
+
$ retell batch-calls create --from-number +14157774444 --tasks tasks.json
|
|
6308
|
+
$ retell batch-calls create --from-number +1 --tasks tasks.json --name "Outreach Apr"
|
|
6309
|
+
`
|
|
6310
|
+
).action(async (options) => {
|
|
6311
|
+
await createBatchCallCommand(options);
|
|
6312
|
+
});
|
|
6313
|
+
var llms = program.command("llms").description("Manage Retell LLM response engines");
|
|
6314
|
+
llms.command("list").description("List Retell LLMs").option("-l, --limit <n>", "Maximum number to return").option("--pagination-key <key>", "LLM id to start from").option(
|
|
6315
|
+
"--pagination-key-version <n>",
|
|
6316
|
+
"Version paired with --pagination-key"
|
|
6317
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6318
|
+
await listLlmsCommand(options);
|
|
6319
|
+
});
|
|
6320
|
+
llms.command("get <llm_id>").description("Get a specific Retell LLM").option("--version <n>", "Specific version to retrieve (defaults to latest)").option("--fields <fields>", "Comma-separated list of fields to return").action(async (llmId, options) => {
|
|
6321
|
+
await getLlmCommand(llmId, options);
|
|
6322
|
+
});
|
|
6323
|
+
llms.command("create").description("Create a new Retell LLM (simple flags or full --file)").option("-f, --file <path>", "Path to JSON file with the full LLM body").option("--general-prompt <text>", "General system prompt").option("--model <model>", "Text LLM model (e.g. gpt-4.1)").option("--s2s-model <model>", "Speech-to-speech model").option("--start-speaker <who>", "'user' or 'agent'").option("--begin-message <msg>", "First agent utterance").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6324
|
+
await createLlmCommand(options);
|
|
6325
|
+
});
|
|
6326
|
+
llms.command("update <llm_id>").description("Update a Retell LLM (body via --file)").requiredOption("-f, --file <path>", "Path to JSON file with LLM update body").option("--version <n>", "Specific version to update").option("--fields <fields>", "Comma-separated list of fields to return").action(async (llmId, options) => {
|
|
6327
|
+
await updateLlmCommand(llmId, options);
|
|
6328
|
+
});
|
|
6329
|
+
llms.command("delete <llm_id>").description("Delete a Retell LLM").action(async (llmId) => {
|
|
6330
|
+
await deleteLlmCommand(llmId);
|
|
6331
|
+
});
|
|
6332
|
+
var voices = program.command("voices").description("Manage and search voice resources");
|
|
6333
|
+
voices.command("list").description("List all voices available to this account").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6334
|
+
await listVoicesCommand(options);
|
|
6335
|
+
});
|
|
6336
|
+
voices.command("get <voice_id>").description("Get a specific voice").option("--fields <fields>", "Comma-separated list of fields to return").action(async (voiceId, options) => {
|
|
6337
|
+
await getVoiceCommand(voiceId, options);
|
|
6338
|
+
});
|
|
6339
|
+
voices.command("add-resource").description("Add a community voice to the account's library").requiredOption(
|
|
6340
|
+
"--provider-voice-id <id>",
|
|
6341
|
+
"Voice id assigned by the provider"
|
|
6342
|
+
).requiredOption("--voice-name <name>", "Custom name for the voice").option(
|
|
6343
|
+
"--voice-provider <p>",
|
|
6344
|
+
"elevenlabs, cartesia, minimax, or fish_audio"
|
|
6345
|
+
).option(
|
|
6346
|
+
"--public-user-id <id>",
|
|
6347
|
+
"ElevenLabs only: public user id of the owner"
|
|
6348
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6349
|
+
await addVoiceResourceCommand(options);
|
|
6350
|
+
});
|
|
6351
|
+
voices.command("clone").description("Clone a voice from one or more audio files").requiredOption("--voice-name <name>", "Name for the cloned voice").requiredOption(
|
|
6352
|
+
"--voice-provider <p>",
|
|
6353
|
+
"elevenlabs, cartesia, minimax, fish_audio, or platform"
|
|
6354
|
+
).option(
|
|
6355
|
+
"--file <path>",
|
|
6356
|
+
"Audio file to use for cloning (repeat for multiple files)",
|
|
6357
|
+
(value, previous = []) => [...previous, value],
|
|
6358
|
+
[]
|
|
6359
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
|
|
6360
|
+
"after",
|
|
6361
|
+
`
|
|
6362
|
+
Examples:
|
|
6363
|
+
$ retell voices clone --voice-name "Dev Clone" --voice-provider elevenlabs --file sample.wav
|
|
6364
|
+
$ retell voices clone --voice-name "Multi" --voice-provider elevenlabs --file one.wav --file two.wav
|
|
6365
|
+
`
|
|
6366
|
+
).action(async (options) => {
|
|
6367
|
+
await cloneVoiceCommand(options);
|
|
6368
|
+
});
|
|
6369
|
+
voices.command("search").description("Search community voices from a provider").requiredOption(
|
|
6370
|
+
"--search-query <query>",
|
|
6371
|
+
"Search query (name, description, or id)"
|
|
6372
|
+
).option(
|
|
6373
|
+
"--voice-provider <p>",
|
|
6374
|
+
"elevenlabs, cartesia, minimax, or fish_audio"
|
|
6375
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6376
|
+
await searchVoicesCommand(options);
|
|
6377
|
+
});
|
|
6378
|
+
var chats = program.command("chats").description("Manage chat sessions with chat agents");
|
|
6379
|
+
chats.command("create").description("Start a new chat session").requiredOption("--agent-id <id>", "Chat agent id").option("--agent-version <n>", "Specific chat agent version").option("--metadata <json>", "Inline JSON or @path for chat metadata").option(
|
|
6380
|
+
"--dynamic-variables <json>",
|
|
6381
|
+
"Inline JSON or @path for dynamic variables"
|
|
6382
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6383
|
+
await createChatCommand(options);
|
|
6384
|
+
});
|
|
6385
|
+
chats.command("get <chat_id>").description("Get a chat by id").option("--fields <fields>", "Comma-separated list of fields to return").action(async (chatId, options) => {
|
|
6386
|
+
await getChatCommand(chatId, options);
|
|
6387
|
+
});
|
|
6388
|
+
chats.command("list").description("List chats").option("-l, --limit <n>", "Maximum number to return").option("--pagination-key <key>", "Chat id to start from").option("--sort-order <order>", "ascending or descending").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6389
|
+
await listChatsCommand(options);
|
|
6390
|
+
});
|
|
6391
|
+
chats.command("update <chat_id>").description("Update metadata and storage settings on a chat").option("--metadata <json>", "Inline JSON or @path for chat metadata").option(
|
|
6392
|
+
"--custom-attributes <json>",
|
|
6393
|
+
"Inline JSON or @path for custom attributes"
|
|
6394
|
+
).option(
|
|
6395
|
+
"--dynamic-variables <json>",
|
|
6396
|
+
"Inline JSON or @path overriding dynamic variables"
|
|
6397
|
+
).option(
|
|
6398
|
+
"--data-storage-setting <value>",
|
|
6399
|
+
"everything | basic_attributes_only"
|
|
6400
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (chatId, options) => {
|
|
6401
|
+
await updateChatCommand(chatId, options);
|
|
6402
|
+
});
|
|
6403
|
+
chats.command("complete").description("Send a user message and get the agent's completion").requiredOption("--chat-id <id>", "Chat id").requiredOption("--content <text>", "User message content").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6404
|
+
await chatCompleteCommand(options);
|
|
6405
|
+
});
|
|
6406
|
+
chats.command("sms").description("Create an SMS-backed chat session").requiredOption(
|
|
6407
|
+
"--from-number <number>",
|
|
6408
|
+
"Sender number (must be SMS-capable)"
|
|
6409
|
+
).requiredOption("--to-number <number>", "Recipient number").option("--override-agent-id <id>", "One-time agent override").option("--override-agent-version <n>", "Override agent version").option("--metadata <json>", "Inline JSON or @path for chat metadata").option(
|
|
6410
|
+
"--dynamic-variables <json>",
|
|
6411
|
+
"Inline JSON or @path for dynamic variables"
|
|
6412
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6413
|
+
await createSmsChatCommand(options);
|
|
6414
|
+
});
|
|
6415
|
+
chats.command("end <chat_id>").description("End an active chat session").action(async (chatId) => {
|
|
6416
|
+
await endChatCommand(chatId);
|
|
6417
|
+
});
|
|
6418
|
+
var chatAgents = program.command("chat-agents").description("Manage chat agents (text/SMS mode)");
|
|
6419
|
+
chatAgents.command("list").description("List chat agents").option("-l, --limit <n>", "Maximum number to return").option("--pagination-key <key>", "Chat agent id to start from").option(
|
|
6420
|
+
"--pagination-key-version <n>",
|
|
6421
|
+
"Version paired with --pagination-key"
|
|
6422
|
+
).option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6423
|
+
await listChatAgentsCommand(options);
|
|
6424
|
+
});
|
|
6425
|
+
chatAgents.command("get <agent_id>").description("Get a chat agent").option("--version <n>", "Specific version to retrieve").option("--fields <fields>", "Comma-separated list of fields to return").action(async (agentId, options) => {
|
|
6426
|
+
await getChatAgentCommand(agentId, options);
|
|
6427
|
+
});
|
|
6428
|
+
chatAgents.command("create").description("Create a new chat agent").option("-f, --file <path>", "Path to JSON file with full agent body").option("--name <name>", "Agent name").option("--llm-id <id>", "Attach a retell-llm response engine").option("--flow-id <id>", "Attach a conversation-flow response engine").option("--custom-llm <url>", "Custom-LLM websocket URL").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6429
|
+
await createChatAgentCommand(options);
|
|
6430
|
+
});
|
|
6431
|
+
chatAgents.command("update <agent_id>").description("Update a chat agent (body via --file)").requiredOption("-f, --file <path>", "Path to JSON file with update body").option("--fields <fields>", "Comma-separated list of fields to return").action(async (agentId, options) => {
|
|
6432
|
+
await updateChatAgentCommand(agentId, options);
|
|
6433
|
+
});
|
|
6434
|
+
chatAgents.command("delete <agent_id>").description("Delete a chat agent").action(async (agentId) => {
|
|
6435
|
+
await deleteChatAgentCommand(agentId);
|
|
6436
|
+
});
|
|
6437
|
+
chatAgents.command("versions <agent_id>").description("List all versions of a chat agent").option("--fields <fields>", "Comma-separated list of fields to return").action(async (agentId, options) => {
|
|
6438
|
+
await chatAgentVersionsCommand(agentId, options);
|
|
6439
|
+
});
|
|
6440
|
+
chatAgents.command("publish <agent_id>").description("Publish the draft configuration of a chat agent").action(async (agentId) => {
|
|
6441
|
+
await publishChatAgentCommand(agentId);
|
|
6442
|
+
});
|
|
6443
|
+
var flowComponents = program.command("flow-components").description("Manage reusable conversation-flow components");
|
|
6444
|
+
flowComponents.command("list").description("List flow components").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6445
|
+
await listFlowComponentsCommand(options);
|
|
6446
|
+
});
|
|
6447
|
+
flowComponents.command("get <component_id>").description("Get a flow component").option("--fields <fields>", "Comma-separated list of fields to return").action(async (componentId, options) => {
|
|
6448
|
+
await getFlowComponentCommand(componentId, options);
|
|
6449
|
+
});
|
|
6450
|
+
flowComponents.command("create").description("Create a new flow component (body via --file)").requiredOption("-f, --file <path>", "Path to JSON file with the full body").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6451
|
+
await createFlowComponentCommand(options);
|
|
6452
|
+
});
|
|
6453
|
+
flowComponents.command("update <component_id>").description("Update a flow component (body via --file)").requiredOption("-f, --file <path>", "Path to JSON file with update body").option("--fields <fields>", "Comma-separated list of fields to return").action(async (componentId, options) => {
|
|
6454
|
+
await updateFlowComponentCommand(componentId, options);
|
|
6455
|
+
});
|
|
6456
|
+
flowComponents.command("delete <component_id>").description("Delete a flow component").action(async (componentId) => {
|
|
6457
|
+
await deleteFlowComponentCommand(componentId);
|
|
6458
|
+
});
|
|
6459
|
+
var concurrency = program.command("concurrency").description("View the org's call concurrency and limits");
|
|
6460
|
+
concurrency.command("get").description("Get current call concurrency and limits").option("--fields <fields>", "Comma-separated list of fields to return").action(async (options) => {
|
|
6461
|
+
await getConcurrencyCommand(options);
|
|
6462
|
+
});
|
|
6463
|
+
program.commands.find((c) => c.name() === "agents").command("mcp-tools <agent_id>").description("List the MCP tools available to an agent").requiredOption("--mcp-id <id>", "ID of the MCP server").option("--component-id <id>", "Component id (if MCP is under a component)").option("--version <n>", "Agent version (defaults to latest)").option("--fields <fields>", "Comma-separated list of fields to return").action(async (agentId, options) => {
|
|
6464
|
+
await agentMcpToolsCommand(agentId, options);
|
|
6465
|
+
});
|
|
4723
6466
|
program.parse(process.argv);
|
|
4724
6467
|
if (!process.argv.slice(2).length) {
|
|
4725
6468
|
program.outputHelp();
|