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