retell-cli 1.5.0 → 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/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 import_fs17 = require("fs");
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 calls = await client.call.list({
386
+ const calls2 = await client.call.list({
387
387
  limit: options.limit || 50
388
388
  });
389
389
  const output = options.fields ? filterFields(
390
- calls,
390
+ calls2,
391
391
  options.fields.split(",").map((f) => f.trim())
392
- ) : calls;
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
- sourceId,
3645
- { knowledge_base_id: knowledgeBaseId }
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,
@@ -3846,97 +3845,146 @@ async function getPhoneNumberCommand(phoneNumber, options = {}) {
3846
3845
  }
3847
3846
  }
3848
3847
 
3849
- // src/commands/phone-numbers/import.ts
3848
+ // src/services/weighted-agents.ts
3850
3849
  function parseWeightedAgents(spec) {
3851
3850
  const entries = spec.split(",").map((s) => s.trim()).filter(Boolean);
3852
3851
  if (entries.length === 0) {
3853
- throw new Error("Empty agent spec. Provide at least one agent ID.");
3852
+ throwValidation("Empty agent spec. Provide at least one agent ID.");
3854
3853
  }
3855
3854
  const agents2 = entries.map((entry) => {
3856
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
+ }
3857
3865
  if (parts.length === 1) {
3858
- return { agent_id: parts[0], weight: -1 };
3866
+ return { agent_id: agentId, weight: -1 };
3859
3867
  }
3860
- if (parts.length === 2) {
3861
- const weight = Number(parts[1]);
3862
- if (isNaN(weight) || weight <= 0 || weight > 1) {
3863
- throw new Error(
3864
- `Invalid weight "${parts[1]}" for agent "${parts[0]}". Weight must be a number between 0 (exclusive) and 1 (inclusive).`
3865
- );
3866
- }
3867
- return { agent_id: parts[0], weight };
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
+ );
3868
3873
  }
3869
- throw new Error(`Invalid agent spec "${entry}". Expected format: agent_id or agent_id:weight`);
3874
+ return { agent_id: agentId, weight };
3870
3875
  });
3871
3876
  const allDefault = agents2.every((a) => a.weight === -1);
3872
3877
  if (allDefault) {
3873
3878
  const w = 1 / agents2.length;
3874
3879
  for (const a of agents2) a.weight = w;
3875
3880
  } else if (agents2.some((a) => a.weight === -1)) {
3876
- throw new Error(
3881
+ throwValidation(
3877
3882
  "Cannot mix agents with and without weights. Either specify weights for all agents or none."
3878
3883
  );
3879
3884
  }
3880
3885
  const sum = agents2.reduce((s, a) => s + a.weight, 0);
3881
3886
  if (Math.abs(sum - 1) > 1e-3) {
3882
- throw new Error(
3887
+ throwValidation(
3883
3888
  `Agent weights must sum to 1.0, but got ${sum.toFixed(4)}.`
3884
3889
  );
3885
3890
  }
3886
3891
  return agents2;
3887
3892
  }
3888
- async function importPhoneNumberCommand(options) {
3889
- if (options.inboundAgent && options.inboundAgents) {
3890
- process.stderr.write(
3891
- "Error: --inbound-agent and --inbound-agents are mutually exclusive. Use one or the other.\n"
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."
3892
3909
  );
3893
- process.exit(1);
3894
- return;
3895
3910
  }
3896
- if (options.outboundAgent && options.outboundAgents) {
3897
- process.stderr.write(
3898
- "Error: --outbound-agent and --outbound-agents are mutually exclusive. Use one or the other.\n"
3911
+ if (flags.outboundAgent && flags.outboundAgents) {
3912
+ throwValidation(
3913
+ "--outbound-agent and --outbound-agents are mutually exclusive. Use one or the other."
3899
3914
  );
3900
- process.exit(1);
3901
- return;
3902
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
+
3955
+ // src/commands/phone-numbers/import.ts
3956
+ async function importPhoneNumberCommand(options) {
3903
3957
  try {
3904
- const client = getRetellClient();
3905
3958
  const importParams = {
3906
- phone_number: options.number,
3907
- termination_uri: options.terminationUri
3959
+ phone_number: requireNonEmpty(options.number, "--number"),
3960
+ termination_uri: requireNonEmpty(
3961
+ options.terminationUri,
3962
+ "--termination-uri"
3963
+ )
3908
3964
  };
3909
3965
  if (options.nickname) {
3910
3966
  importParams.nickname = options.nickname;
3911
3967
  }
3912
- if (options.inboundAgent) {
3913
- importParams.inbound_agents = [
3914
- { agent_id: options.inboundAgent, weight: 1 }
3915
- ];
3916
- } else if (options.inboundAgents) {
3917
- importParams.inbound_agents = parseWeightedAgents(options.inboundAgents);
3918
- }
3919
- if (options.outboundAgent) {
3920
- importParams.outbound_agents = [
3921
- { agent_id: options.outboundAgent, weight: 1 }
3922
- ];
3923
- } else if (options.outboundAgents) {
3924
- importParams.outbound_agents = parseWeightedAgents(
3925
- options.outboundAgents
3926
- );
3927
- }
3928
- if (options.inboundSmsAgents) {
3929
- importParams.inbound_sms_agents = parseWeightedAgents(options.inboundSmsAgents);
3930
- }
3931
- if (options.outboundSmsAgents) {
3932
- importParams.outbound_sms_agents = parseWeightedAgents(options.outboundSmsAgents);
3933
- }
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
+ );
3934
3981
  if (options.sipUsername) {
3935
3982
  importParams.sip_trunk_auth_username = options.sipUsername;
3936
3983
  }
3937
3984
  if (options.sipPassword) {
3938
3985
  importParams.sip_trunk_auth_password = options.sipPassword;
3939
3986
  }
3987
+ const client = getRetellClient();
3940
3988
  const pn = await client.phoneNumber.import(importParams);
3941
3989
  const output = options.fields ? filterFields(
3942
3990
  pn,
@@ -3948,236 +3996,1532 @@ async function importPhoneNumberCommand(options) {
3948
3996
  }
3949
3997
  }
3950
3998
 
3951
- // src/index.ts
3952
- var packageJson = JSON.parse(
3953
- (0, import_fs17.readFileSync)((0, import_path6.join)(__dirname, "../package.json"), "utf-8")
3954
- );
3955
- var program = new import_commander.Command();
3956
- 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);
3957
- program.command("login").description("Authenticate with Retell AI").addHelpText(
3958
- "after",
3959
- `
3960
- Examples:
3961
- $ retell login
3962
- # Enter your API key when prompted
3963
- # Creates .retellrc.json in current directory
3964
- `
3965
- ).action(async () => {
3966
- await loginCommand();
3967
- });
3968
- var transcripts = program.command("transcripts").description("Manage call transcripts");
3969
- transcripts.command("list").description("List all call transcripts").option(
3970
- "-l, --limit <number>",
3971
- "Maximum number of calls to return (default: 50)",
3972
- "50"
3973
- ).option(
3974
- "--fields <fields>",
3975
- "Comma-separated list of fields to return (e.g., call_id,call_status,metadata.duration)"
3976
- ).addHelpText(
3977
- "after",
3978
- `
3979
- Examples:
3980
- $ retell transcripts list
3981
- $ retell transcripts list --limit 100
3982
- $ retell transcripts list --fields call_id,call_status
3983
- $ retell transcripts list | jq '.[] | select(.call_status == "error")'
3984
- `
3985
- ).action(async (options) => {
3986
- const limit = parseInt(options.limit, 10);
3987
- if (isNaN(limit) || limit < 1) {
3988
- console.error("Error: limit must be a positive number");
3989
- 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`);
3990
4003
  }
3991
- await listTranscriptsCommand({
3992
- limit,
3993
- fields: options.fields
3994
- });
3995
- });
3996
- transcripts.command("get <call_id>").description("Get a specific call transcript").option(
3997
- "--fields <fields>",
3998
- "Comma-separated list of fields to return (e.g., call_id,metadata.duration,analysis)"
3999
- ).addHelpText(
4000
- "after",
4001
- `
4002
- Examples:
4003
- $ retell transcripts get call_abc123
4004
- $ retell transcripts get call_abc123 --fields call_id,metadata.duration
4005
- $ retell transcripts get call_abc123 | jq '.transcript_object'
4006
- `
4007
- ).action(async (callId, options) => {
4008
- await getTranscriptCommand(callId, {
4009
- fields: options.fields
4010
- });
4011
- });
4012
- transcripts.command("analyze <call_id>").description(
4013
- "Analyze a call transcript with performance metrics and insights"
4014
- ).option(
4015
- "--fields <fields>",
4016
- "Comma-separated list of fields to return (e.g., call_id,performance,analysis.summary)"
4017
- ).option(
4018
- "--raw",
4019
- "Return unmodified API response instead of enriched analysis"
4020
- ).option(
4021
- "--hotspots-only",
4022
- "Return only conversation hotspots/issues for troubleshooting"
4023
- ).option(
4024
- "--latency-threshold <ms>",
4025
- `Latency threshold in ms for hotspot detection (default: ${DEFAULT_LATENCY_THRESHOLD})`,
4026
- String(DEFAULT_LATENCY_THRESHOLD)
4027
- ).option(
4028
- "--silence-threshold <ms>",
4029
- `Silence threshold in ms for hotspot detection (default: ${DEFAULT_SILENCE_THRESHOLD})`,
4030
- String(DEFAULT_SILENCE_THRESHOLD)
4031
- ).addHelpText(
4032
- "after",
4033
- `
4034
- Examples:
4035
- $ retell transcripts analyze call_abc123
4036
- $ retell transcripts analyze call_abc123 --fields call_id,performance
4037
- $ retell transcripts analyze call_abc123 --raw
4038
- $ retell transcripts analyze call_abc123 --raw --fields call_id,transcript_object
4039
- $ retell transcripts analyze call_abc123 --hotspots-only
4040
- $ retell transcripts analyze call_abc123 --hotspots-only --latency-threshold 1500
4041
- $ retell transcripts analyze call_abc123 --hotspots-only --fields hotspots
4042
- $ retell transcripts analyze call_abc123 | jq '.performance.latency_p50_ms'
4043
- `
4044
- ).action(async (callId, options) => {
4045
- await analyzeTranscriptCommand(callId, {
4046
- fields: options.fields,
4047
- raw: options.raw,
4048
- hotspotsOnly: options.hotspotsOnly,
4049
- latencyThreshold: options.latencyThreshold ? parseInt(options.latencyThreshold) : void 0,
4050
- silenceThreshold: options.silenceThreshold ? parseInt(options.silenceThreshold) : void 0
4051
- });
4052
- });
4053
- 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(
4054
- "--since <date>",
4055
- "Filter calls after this date (YYYY-MM-DD or ISO format)"
4056
- ).option(
4057
- "--until <date>",
4058
- "Filter calls before this date (YYYY-MM-DD or ISO format)"
4059
- ).option("--limit <number>", "Maximum number of results (default: 50)", "50").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
4060
- "after",
4061
- `
4062
- Examples:
4063
- $ retell transcripts search --status error
4064
- $ retell transcripts search --agent-id agent_123 --since 2025-11-01
4065
- $ retell transcripts search --status error --limit 10
4066
- $ retell transcripts search --status error --fields call_id,agent_id,call_status
4067
- $ retell transcripts search --since 2025-11-01 --until 2025-11-15
4068
- `
4069
- ).action(async (options) => {
4070
- await searchTranscriptsCommand({
4071
- status: options.status,
4072
- agentId: options.agentId,
4073
- since: options.since,
4074
- until: options.until,
4075
- limit: options.limit ? Number(options.limit) : void 0,
4076
- fields: options.fields
4077
- });
4078
- });
4079
- var agents = program.command("agents").description("Manage agents");
4080
- agents.command("list").description("List all agents").option(
4081
- "-l, --limit <number>",
4082
- "Maximum number of agents to return (default: 100)",
4083
- "100"
4084
- ).option(
4085
- "--fields <fields>",
4086
- "Comma-separated list of fields to return (e.g., agent_id,agent_name,response_engine_type)"
4087
- ).addHelpText(
4088
- "after",
4089
- `
4090
- Examples:
4091
- $ retell agents list
4092
- $ retell agents list --limit 10
4093
- $ retell agents list --fields agent_id,agent_name
4094
- $ retell agents list | jq '.[] | select(.response_engine.type == "retell-llm")'
4095
- `
4096
- ).action(async (options) => {
4097
- const limit = parseInt(options.limit, 10);
4098
- if (isNaN(limit) || limit < 1) {
4099
- console.error("Error: limit must be a positive number");
4100
- process.exit(1);
4004
+ const v = Number(value);
4005
+ if (!Number.isFinite(v)) {
4006
+ throwValidation3(`${flagName} must be a number`);
4101
4007
  }
4102
- await listAgentsCommand({
4103
- limit,
4104
- fields: options.fields
4105
- });
4106
- });
4107
- agents.command("info <agent_id>").description("Get detailed agent information").option(
4108
- "--fields <fields>",
4109
- "Comma-separated list of fields to return (e.g., agent_name,response_engine.type,voice_config)"
4110
- ).addHelpText(
4111
- "after",
4112
- `
4113
- Examples:
4114
- $ retell agents info agent_123abc
4115
- $ retell agents info agent_123abc --fields agent_name,response_engine.type
4116
- $ retell agents info agent_123abc | jq '.response_engine.type'
4117
- `
4118
- ).action(async (agentId, options) => {
4119
- await agentInfoCommand(agentId, {
4120
- fields: options.fields
4121
- });
4122
- });
4123
- 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(
4124
- "--flow-id <id>",
4125
- "Conversation Flow ID (creates conversation-flow response engine)"
4126
- ).option("--custom-llm <url>", "Custom LLM WebSocket URL").option(
4127
- "-f, --file <path>",
4128
- "Full agent config from JSON file (overrides other options)"
4129
- ).option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
4130
- "after",
4131
- `
4132
- Examples:
4133
- $ retell agents create --voice 11labs-Adrian --llm-id llm_xxx --name "Test Agent"
4134
- $ retell agents create --voice 11labs-Adrian --flow-id cf_xxx
4135
- $ retell agents create --file agent-config.json
4136
- `
4137
- ).action(async (options) => {
4138
- await createAgentCommand(options);
4139
- });
4140
- agents.command("delete <agent_id>").description("Delete an agent").addHelpText(
4141
- "after",
4142
- `
4143
- Examples:
4144
- $ retell agents delete agent_123abc
4145
- `
4146
- ).action(async (agentId) => {
4147
- await deleteAgentCommand(agentId);
4148
- });
4149
- agents.command("versions <agent_id>").description("List all versions of an agent").option("--fields <fields>", "Comma-separated list of fields to return").addHelpText(
4150
- "after",
4151
- `
4152
- Examples:
4153
- $ retell agents versions agent_123abc
4154
- $ retell agents versions agent_123abc --fields version,is_published
4155
- `
4156
- ).action(async (agentId, options) => {
4157
- await agentVersionsCommand(agentId, options);
4158
- });
4159
- var prompts = program.command("prompts").description("Manage agent prompts");
4160
- prompts.command("pull <agent_id>").description("Download agent prompts to a local file").option(
4161
- "-o, --output <path>",
4162
- "Output file path (default: .retell-prompts/<agent_id>.json)",
4163
- ".retell-prompts"
4164
- ).addHelpText(
4165
- "after",
4166
- `
4167
- Examples:
4168
- $ retell prompts pull agent_123abc
4169
- $ retell prompts pull agent_123abc --output my-prompts.json
4170
- `
4171
- ).action(async (agentId, options) => {
4172
- await pullPromptsCommand(agentId, options);
4173
- });
4174
- prompts.command("diff <agent_id>").description("Show differences between local and remote prompts").option(
4175
- "-s, --source <path>",
4176
- "Source directory path (default: .retell-prompts)",
4177
- ".retell-prompts"
4178
- ).option("-f, --fields <fields>", "Comma-separated list of fields to return").addHelpText(
4179
- "after",
4180
- `
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",
5524
+ `
4181
5525
  Examples:
4182
5526
  $ retell prompts diff agent_123abc
4183
5527
  $ retell prompts diff agent_123abc --source ./custom-prompts
@@ -4231,7 +5575,7 @@ Examples:
4231
5575
  `
4232
5576
  ).action(async (agentId, options) => {
4233
5577
  await getAgentCommand(agentId, {
4234
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0,
5578
+ version: parseFlagOrExit(options.engineVersion, "--engine-version"),
4235
5579
  fields: options.fields
4236
5580
  });
4237
5581
  });
@@ -4270,7 +5614,7 @@ Note: Run 'retell agent-publish <agent_id>' after updating to publish changes.
4270
5614
  await updateAgentCommand(agentId, {
4271
5615
  file: options.file,
4272
5616
  dryRun: options.dryRun,
4273
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0
5617
+ version: parseFlagOrExit(options.engineVersion, "--engine-version")
4274
5618
  });
4275
5619
  });
4276
5620
  var tools = program.command("tools").description("Manage agent tools (custom functions, webhooks, etc.)");
@@ -4467,7 +5811,7 @@ Test case JSON format:
4467
5811
  file: options.file,
4468
5812
  llmId: options.llmId,
4469
5813
  flowId: options.flowId,
4470
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0
5814
+ version: parseFlagOrExit(options.engineVersion, "--engine-version")
4471
5815
  });
4472
5816
  });
4473
5817
  testsCases.command("update <test_case_definition_id>").description("Update an existing test case definition from a JSON file").requiredOption(
@@ -4545,7 +5889,7 @@ Examples:
4545
5889
  llmId: options.llmId,
4546
5890
  flowId: options.flowId,
4547
5891
  cases: options.cases,
4548
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0
5892
+ version: parseFlagOrExit(options.engineVersion, "--engine-version")
4549
5893
  });
4550
5894
  });
4551
5895
  var testsRuns = tests.command("runs").description("View test run results");
@@ -4677,10 +6021,10 @@ Examples:
4677
6021
  $ retell flows list --fields conversation_flow_id,version,start_speaker
4678
6022
  `
4679
6023
  ).action(async (options) => {
4680
- const limit = parseInt(options.limit, 10);
4681
- if (isNaN(limit) || limit < 1 || limit > 1e3) {
6024
+ const limit = parseFlagOrExit(options.limit, "--limit") ?? 50;
6025
+ if (limit < 1 || limit > 1e3) {
4682
6026
  console.error(
4683
- "Error: limit must be a positive number between 1 and 1000"
6027
+ "Error: --limit must be a positive number between 1 and 1000"
4684
6028
  );
4685
6029
  process.exit(1);
4686
6030
  }
@@ -4702,7 +6046,7 @@ Examples:
4702
6046
  `
4703
6047
  ).action(async (conversationFlowId, options) => {
4704
6048
  await getFlowCommand(conversationFlowId, {
4705
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0,
6049
+ version: parseFlagOrExit(options.engineVersion, "--engine-version"),
4706
6050
  fields: options.fields
4707
6051
  });
4708
6052
  });
@@ -4744,7 +6088,7 @@ Examples:
4744
6088
  ).action(async (conversationFlowId, options) => {
4745
6089
  await updateFlowCommand(conversationFlowId, {
4746
6090
  file: options.file,
4747
- version: options.engineVersion ? parseInt(options.engineVersion, 10) : void 0
6091
+ version: parseFlagOrExit(options.engineVersion, "--engine-version")
4748
6092
  });
4749
6093
  });
4750
6094
  flows.command("delete <conversation_flow_id>").description("Delete a conversation flow").addHelpText(
@@ -4777,7 +6121,19 @@ Examples:
4777
6121
  ).action(async (phoneNumber, options) => {
4778
6122
  await getPhoneNumberCommand(phoneNumber, options);
4779
6123
  });
4780
- 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("--inbound-agent <id>", "Single agent for inbound calls (shorthand for weight 1)").option("--outbound-agent <id>", "Single agent for outbound calls (shorthand for weight 1)").option("--inbound-agents <spec>", "Weighted inbound agents (format: id:weight,id:weight)").option("--outbound-agents <spec>", "Weighted outbound agents (format: id:weight,id:weight)").option("--inbound-sms-agents <spec>", "Weighted inbound SMS agents (format: id:weight,id:weight)").option("--outbound-sms-agents <spec>", "Weighted outbound SMS agents (format: id:weight,id:weight)").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(
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(
4781
6137
  "after",
4782
6138
  `
4783
6139
  Examples:
@@ -4785,10 +6141,328 @@ Examples:
4785
6141
  $ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com --nickname "Support Line"
4786
6142
  $ retell phone-numbers import --number +14157774444 --termination-uri someuri.pstn.twilio.com --inbound-agent agent_xxx
4787
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.
4788
6146
  `
4789
6147
  ).action(async (options) => {
4790
6148
  await importPhoneNumberCommand(options);
4791
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
+ });
4792
6466
  program.parse(process.argv);
4793
6467
  if (!process.argv.slice(2).length) {
4794
6468
  program.outputHelp();