retell-sync-cli 3.11.0 → 3.13.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 (2) hide show
  1. package/dist/cli.js +31 -130
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -133802,8 +133802,6 @@ async function formatWithPrettier(content, opts) {
133802
133802
  // src/lib/utils.ts
133803
133803
  var DEFAULT_AGENTS_DIR = "./agents";
133804
133804
  var FILE_HASH_LENGTH = 6;
133805
- var CONFIG_FORMATS = ["yaml", "yml", "json", "jsonc"];
133806
- var DEFAULT_CONFIG_FORMAT = "yaml";
133807
133805
  async function readMarkdown(content) {
133808
133806
  const trimmed = content.trim();
133809
133807
  if (!trimmed.startsWith("---")) {
@@ -133843,69 +133841,9 @@ function readJson2(content, schema) {
133843
133841
  }
133844
133842
  return parsed;
133845
133843
  }
133846
- function stripJsoncComments(content) {
133847
- return content.split(`
133848
- `).map((line3) => {
133849
- let inString = false;
133850
- let escaped = false;
133851
- for (let i5 = 0;i5 < line3.length; i5++) {
133852
- const char = line3[i5];
133853
- if (escaped) {
133854
- escaped = false;
133855
- continue;
133856
- }
133857
- if (char === "\\") {
133858
- escaped = true;
133859
- continue;
133860
- }
133861
- if (char === '"') {
133862
- inString = !inString;
133863
- continue;
133864
- }
133865
- if (!inString && char === "/" && line3[i5 + 1] === "/") {
133866
- return line3.slice(0, i5).trimEnd();
133867
- }
133868
- }
133869
- return line3;
133870
- }).join(`
133871
- `);
133872
- }
133873
- function readJsonc(content, schema) {
133874
- const stripped = stripJsoncComments(content);
133875
- return readJson2(stripped, schema);
133876
- }
133877
133844
  async function writeJson(obj) {
133878
133845
  return formatWithPrettier(JSON.stringify(obj), { parser: "json" });
133879
133846
  }
133880
- async function writeJsonc(obj, { comments = {} } = {}) {
133881
- const json2 = await formatWithPrettier(JSON.stringify(obj), {
133882
- parser: "json"
133883
- });
133884
- if (Object.keys(comments).length === 0) {
133885
- return json2;
133886
- }
133887
- const lines = json2.split(`
133888
- `);
133889
- const result2 = [];
133890
- let isFirstKey = true;
133891
- for (const line3 of lines) {
133892
- const keyMatch = line3.match(/^ {2}"([^"]+)":\s*/);
133893
- if (keyMatch?.[1]) {
133894
- const key2 = keyMatch[1];
133895
- const comment = comments[key2];
133896
- if (comment) {
133897
- if (!isFirstKey) {
133898
- result2.push("");
133899
- }
133900
- result2.push(` // ${comment}`);
133901
- }
133902
- isFirstKey = false;
133903
- }
133904
- result2.push(line3);
133905
- }
133906
- return result2.join(`
133907
- `);
133908
- }
133909
133847
  function readYaml(content, schema) {
133910
133848
  const parsed = import_yaml2.default.parse(content);
133911
133849
  if (schema) {
@@ -134225,10 +134163,9 @@ async function getLocalState({
134225
134163
  }
134226
134164
  async function writeState(state, {
134227
134165
  agentsDir = DEFAULT_AGENTS_DIR,
134228
- configFormat = DEFAULT_CONFIG_FORMAT,
134229
134166
  agentIds = null
134230
134167
  } = {}) {
134231
- const files = await serializeState(state, { agentsDir, configFormat });
134168
+ const files = await serializeState(state, { agentsDir });
134232
134169
  const writtenFiles = new Set;
134233
134170
  for (const [filePath, content] of Object.entries(files)) {
134234
134171
  const fullPath = path15.resolve(filePath);
@@ -134282,13 +134219,7 @@ async function listFilesRecursive(dir) {
134282
134219
  }
134283
134220
  return files;
134284
134221
  }
134285
- async function serializeState(state, {
134286
- agentsDir = DEFAULT_AGENTS_DIR,
134287
- configFormat = DEFAULT_CONFIG_FORMAT
134288
- } = {}) {
134289
- const isYaml = configFormat === "yaml" || configFormat === "yml";
134290
- const isJsonc = configFormat === "jsonc";
134291
- const configExt = configFormat;
134222
+ async function serializeState(state, { agentsDir = DEFAULT_AGENTS_DIR } = {}) {
134292
134223
  const files = {};
134293
134224
  const llmMap = new Map(state.llms.map((llm) => [llm._id, llm]));
134294
134225
  const flowMap = new Map(state.conversationFlows.map((flow) => [flow._id, flow]));
@@ -134301,7 +134232,7 @@ async function serializeState(state, {
134301
134232
  files[path15.join(agentDirPath, "general_prompt.md")] = await writeMarkdown(llmConfig.general_prompt);
134302
134233
  llmConfig.general_prompt = "file://./general_prompt.md";
134303
134234
  }
134304
- files[path15.join(agentDirPath, `llm.${configExt}`)] = isYaml ? await writeYaml(llmConfig, { comments: llmFieldDocs }) : isJsonc ? await writeJsonc(llmConfig, { comments: llmFieldDocs }) : await writeJson(llmConfig);
134235
+ files[path15.join(agentDirPath, "llm.yaml")] = await writeYaml(llmConfig, { comments: llmFieldDocs });
134305
134236
  }
134306
134237
  } else if (agent.response_engine.type === "conversation-flow") {
134307
134238
  const flow = flowMap.get(agent.response_engine.conversation_flow_id);
@@ -134378,7 +134309,7 @@ async function serializeState(state, {
134378
134309
  if (Object.keys(positions).length > 0) {
134379
134310
  files[path15.join(agentDirPath, ".positions.json")] = await writeJson(positions);
134380
134311
  }
134381
- files[path15.join(agentDirPath, `conversation-flow.${configExt}`)] = isYaml ? await writeYaml(flowConfig, { comments: flowFieldDocs }) : isJsonc ? await writeJsonc(flowConfig, { comments: flowFieldDocs }) : await writeJson(flowConfig);
134312
+ files[path15.join(agentDirPath, "conversation-flow.yaml")] = await writeYaml(flowConfig, { comments: flowFieldDocs });
134382
134313
  }
134383
134314
  }
134384
134315
  };
@@ -134403,7 +134334,7 @@ async function serializeState(state, {
134403
134334
  llm_websocket_url: agent.response_engine.llm_websocket_url
134404
134335
  } : voiceAgentConfig;
134405
134336
  await serializeResponseEngine(agent, agentDirPath);
134406
- files[path15.join(agentDirPath, `config.${configExt}`)] = isYaml ? await writeYaml(configToWrite, { comments: agentFieldDocs }) : isJsonc ? await writeJsonc(configToWrite, { comments: agentFieldDocs }) : await writeJson(configToWrite);
134337
+ files[path15.join(agentDirPath, "config.yaml")] = await writeYaml(configToWrite, { comments: agentFieldDocs });
134407
134338
  }
134408
134339
  for (const agent of state.chatAgents) {
134409
134340
  const agentDirName = getAgentDirName(agent);
@@ -134426,7 +134357,7 @@ async function serializeState(state, {
134426
134357
  llm_websocket_url: agent.response_engine.llm_websocket_url
134427
134358
  } : chatAgentConfig;
134428
134359
  await serializeResponseEngine(agent, agentDirPath);
134429
- files[path15.join(agentDirPath, `config.${configExt}`)] = isYaml ? await writeYaml(chatConfigToWrite, { comments: chatAgentFieldDocs }) : isJsonc ? await writeJsonc(chatConfigToWrite, { comments: chatAgentFieldDocs }) : await writeJson(chatConfigToWrite);
134360
+ files[path15.join(agentDirPath, "config.yaml")] = await writeYaml(chatConfigToWrite, { comments: chatAgentFieldDocs });
134430
134361
  }
134431
134362
  return files;
134432
134363
  }
@@ -134461,20 +134392,10 @@ async function canonicalizeFromFiles(files) {
134461
134392
  })
134462
134393
  ])
134463
134394
  }));
134464
- const findConfigFile = (baseName) => {
134465
- for (const ext of ["yaml", "yml", "jsonc", "json"]) {
134466
- const content = fileMap[`${agentDir}/${baseName}.${ext}`];
134467
- if (content) {
134468
- const reader = ext === "jsonc" ? readJsonc : ext === "json" ? readJson2 : readYaml;
134469
- return { content, reader };
134470
- }
134471
- }
134472
- return null;
134473
- };
134474
- const configResult = findConfigFile("config");
134475
- if (!configResult)
134395
+ const configContent = fileMap[`${agentDir}/config.yaml`];
134396
+ if (!configContent)
134476
134397
  continue;
134477
- const agentConfig = configResult.reader(configResult.content, zod_default.looseObject({}));
134398
+ const agentConfig = readYaml(configContent, zod_default.looseObject({}));
134478
134399
  const resolveFileContent = (filePath) => {
134479
134400
  const normalizedPath = filePath.replace(/^\.\//, "");
134480
134401
  const fullPath = `${agentDir}/${normalizedPath}`;
@@ -134486,9 +134407,9 @@ async function canonicalizeFromFiles(files) {
134486
134407
  };
134487
134408
  await resolveFilePlaceholders2(agentConfig, resolveFileContent);
134488
134409
  if (agentMeta.response_engine.type === "retell-llm") {
134489
- const llmResult = findConfigFile("llm");
134490
- if (llmResult) {
134491
- const llmConfig = llmResult.reader(llmResult.content, zod_default.looseObject({}));
134410
+ const llmContent = fileMap[`${agentDir}/llm.yaml`];
134411
+ if (llmContent) {
134412
+ const llmConfig = readYaml(llmContent, zod_default.looseObject({}));
134492
134413
  await resolveFilePlaceholders2(llmConfig, resolveFileContent);
134493
134414
  llms.push({
134494
134415
  ...llmConfig,
@@ -134497,9 +134418,9 @@ async function canonicalizeFromFiles(files) {
134497
134418
  });
134498
134419
  }
134499
134420
  } else if (agentMeta.response_engine.type === "conversation-flow") {
134500
- const flowResult = findConfigFile("conversation-flow");
134501
- if (flowResult) {
134502
- const flowConfig = flowResult.reader(flowResult.content, zod_default.looseObject({}));
134421
+ const flowContent = fileMap[`${agentDir}/conversation-flow.yaml`];
134422
+ if (flowContent) {
134423
+ const flowConfig = readYaml(flowContent, zod_default.looseObject({}));
134503
134424
  await resolveFilePlaceholders2(flowConfig, resolveFileContent);
134504
134425
  const positionsFile = fileMap[`${agentDir}/.positions.json`];
134505
134426
  if (positionsFile) {
@@ -134608,22 +134529,13 @@ async function getLocalTestCases(agentDirPath) {
134608
134529
  const testCases = [];
134609
134530
  for (const testCaseMeta of metadata.test_cases) {
134610
134531
  const testCaseName = toSnakeCase(testCaseMeta.name);
134611
- let configContent = null;
134612
- let reader = readYaml;
134613
- for (const ext of ["yaml", "yml", "jsonc", "json"]) {
134614
- const configPath = path15.join(testsDir, `${testCaseName}.${ext}`);
134615
- const file2 = Bun.file(configPath);
134616
- if (await file2.exists()) {
134617
- configContent = await file2.text();
134618
- reader = ext === "jsonc" ? readJsonc : ext === "json" ? readJson2 : readYaml;
134619
- break;
134620
- }
134621
- }
134622
- if (!configContent) {
134532
+ const configPath = path15.join(testsDir, `${testCaseName}.yaml`);
134533
+ const configFile = Bun.file(configPath);
134534
+ if (!await configFile.exists()) {
134623
134535
  console.warn(`Warning: Could not find config file for test case ${testCaseMeta.name}`);
134624
134536
  continue;
134625
134537
  }
134626
- const config2 = reader(configContent, zod_default.looseObject({}));
134538
+ const config2 = readYaml(await configFile.text(), zod_default.looseObject({}));
134627
134539
  const resolveFileContent = async (filePath) => {
134628
134540
  const normalizedPath = filePath.replace(/^\.\//, "");
134629
134541
  const fullPath = path15.join(testsDir, normalizedPath);
@@ -134646,8 +134558,7 @@ async function updateTestCaseDefinition(testCaseId, update) {
134646
134558
  }
134647
134559
  async function fetchAndWriteTestCases({
134648
134560
  state,
134649
- agentsDir = DEFAULT_AGENTS_DIR,
134650
- configFormat = DEFAULT_CONFIG_FORMAT
134561
+ agentsDir = DEFAULT_AGENTS_DIR
134651
134562
  }) {
134652
134563
  const results = [];
134653
134564
  const allAgents = [
@@ -134681,8 +134592,7 @@ async function fetchAndWriteTestCases({
134681
134592
  }
134682
134593
  await writeTestCases(testCases, {
134683
134594
  agentDirPath,
134684
- responseEngine: engine,
134685
- configFormat
134595
+ responseEngine: engine
134686
134596
  });
134687
134597
  results.push({ agentDir: agentDirName, testCount: testCases.length });
134688
134598
  }
@@ -134690,14 +134600,10 @@ async function fetchAndWriteTestCases({
134690
134600
  }
134691
134601
  async function writeTestCases(testCases, {
134692
134602
  agentDirPath,
134693
- responseEngine,
134694
- configFormat = DEFAULT_CONFIG_FORMAT
134603
+ responseEngine
134695
134604
  }) {
134696
134605
  const testsDir = path15.join(agentDirPath, "tests");
134697
134606
  await fs8.mkdir(testsDir, { recursive: true });
134698
- const isYaml = configFormat === "yaml" || configFormat === "yml";
134699
- const isJsonc = configFormat === "jsonc";
134700
- const configExt = configFormat;
134701
134607
  const metadata = {
134702
134608
  response_engine: responseEngine,
134703
134609
  test_cases: testCases.map((tc3) => ({
@@ -134725,8 +134631,10 @@ async function writeTestCases(testCases, {
134725
134631
  ...config2,
134726
134632
  user_prompt: `file://./${promptFileName}`
134727
134633
  };
134728
- const configFileName = `${testCaseName}.${configExt}`;
134729
- const configContent = isYaml ? await writeYaml(configWithFileRef, { comments: testCaseFieldDocs }) : isJsonc ? await writeJsonc(configWithFileRef, { comments: testCaseFieldDocs }) : await writeJson(configWithFileRef);
134634
+ const configFileName = `${testCaseName}.yaml`;
134635
+ const configContent = await writeYaml(configWithFileRef, {
134636
+ comments: testCaseFieldDocs
134637
+ });
134730
134638
  await Bun.write(path15.join(testsDir, configFileName), configContent);
134731
134639
  writtenFiles.add(configFileName);
134732
134640
  }
@@ -137818,7 +137726,6 @@ async function pullCommand(agentIdArgs, opts, cmd) {
137818
137726
  }
137819
137727
  await pull({
137820
137728
  agentsDir: globalOpts.agentsDir,
137821
- configFormat: globalOpts.configFormat,
137822
137729
  agentIds,
137823
137730
  yes: opts.yes,
137824
137731
  version: version2,
@@ -137834,7 +137741,6 @@ async function pullCommand(agentIdArgs, opts, cmd) {
137834
137741
  }
137835
137742
  async function pull({
137836
137743
  agentsDir = DEFAULT_AGENTS_DIR,
137837
- configFormat = DEFAULT_CONFIG_FORMAT,
137838
137744
  agentIds = null,
137839
137745
  yes = false,
137840
137746
  version: version2,
@@ -137863,14 +137769,13 @@ async function pull({
137863
137769
  const totalAgents = remoteState.voiceAgents.length + remoteState.chatAgents.length;
137864
137770
  spinner.stop(source_default.dim(`${pluralize("agent", totalAgents, true)} (${remoteState.voiceAgents.length} voice, ${remoteState.chatAgents.length} chat), ${pluralize("LLM", remoteState.llms.length, true)}, ${pluralize("flow", remoteState.conversationFlows.length, true)}`));
137865
137771
  const writeSpinner = createSpinner("Writing files...");
137866
- await writeState(remoteState, { agentsDir, configFormat, agentIds });
137772
+ await writeState(remoteState, { agentsDir, agentIds });
137867
137773
  writeSpinner.stop(source_default.green("Done"));
137868
137774
  if (tests) {
137869
137775
  const testSpinner = createSpinner("Fetching test cases...");
137870
137776
  const testResults = await fetchAndWriteTestCases({
137871
137777
  state: remoteState,
137872
- agentsDir,
137873
- configFormat
137778
+ agentsDir
137874
137779
  });
137875
137780
  const totalTests = testResults.reduce((sum, r5) => sum + r5.testCount, 0);
137876
137781
  const agentsWithTests = testResults.filter((r5) => r5.testCount > 0).length;
@@ -137891,7 +137796,6 @@ async function deployCommand(agentIdArgs, opts, cmd) {
137891
137796
  });
137892
137797
  const affectedIds = await deploy({
137893
137798
  agentsDir: globalOpts.agentsDir,
137894
- configFormat: globalOpts.configFormat,
137895
137799
  agentIds,
137896
137800
  dryRun: opts.dryRun,
137897
137801
  verbose: opts.verbose
@@ -137909,7 +137813,6 @@ async function deployCommand(agentIdArgs, opts, cmd) {
137909
137813
  }
137910
137814
  async function deploy({
137911
137815
  agentsDir = DEFAULT_AGENTS_DIR,
137912
- configFormat = DEFAULT_CONFIG_FORMAT,
137913
137816
  agentIds = null,
137914
137817
  dryRun = false,
137915
137818
  verbose = false
@@ -138056,7 +137959,7 @@ async function deploy({
138056
137959
  success2(`Deployed ${pluralize("change", totalChanges, true)}`);
138057
137960
  if (!isQuiet()) {
138058
137961
  bold("Syncing latest state...");
138059
- await pull({ agentsDir, configFormat, agentIds });
137962
+ await pull({ agentsDir, agentIds });
138060
137963
  }
138061
137964
  return [...affectedAgentIds];
138062
137965
  }
@@ -138176,7 +138079,6 @@ async function publishCommand(agentIdArgs, opts, cmd) {
138176
138079
  });
138177
138080
  const publishedIds = await publish({
138178
138081
  agentsDir: globalOpts.agentsDir,
138179
- configFormat: globalOpts.configFormat,
138180
138082
  agentIds,
138181
138083
  dryRun: opts.dryRun
138182
138084
  });
@@ -138193,7 +138095,6 @@ async function publishCommand(agentIdArgs, opts, cmd) {
138193
138095
  }
138194
138096
  async function publish({
138195
138097
  agentsDir = DEFAULT_AGENTS_DIR,
138196
- configFormat = DEFAULT_CONFIG_FORMAT,
138197
138098
  agentIds = null,
138198
138099
  dryRun = false
138199
138100
  } = {}) {
@@ -138264,7 +138165,7 @@ Would publish ${pluralize("agent", agentIdsToPublish.size, true)}:`));
138264
138165
  }
138265
138166
  if (!isQuiet()) {
138266
138167
  bold("Syncing latest state...");
138267
- await pull({ agentsDir, configFormat, agentIds });
138168
+ await pull({ agentsDir, agentIds });
138268
138169
  }
138269
138170
  return publishedAgentIds;
138270
138171
  }
@@ -138339,7 +138240,7 @@ function patchAgentList(agents, publishedIds, publishedVersions, agentNames, dir
138339
138240
 
138340
138241
  // src/cli.ts
138341
138242
  var program2 = new Command;
138342
- program2.name("retell").description("Retell AI agent management CLI").option("-w, --agents-dir <dir>", "Directory for agent files", DEFAULT_AGENTS_DIR).option("-f, --config-format <format>", `Config file format (${CONFIG_FORMATS.join(", ")})`, DEFAULT_CONFIG_FORMAT);
138243
+ program2.name("retell").description("Retell AI agent management CLI").option("-w, --agents-dir <dir>", "Directory for agent files", DEFAULT_AGENTS_DIR);
138343
138244
  program2.command("pull [agentIds...]").description("Pull agents from Retell API (pulls latest draft state by default)").option("-a, --all", "Pull all agents in the account").option("-s, --select", "Force interactive agent selection").option("-y, --yes", "Skip confirmation prompts").option("-v, --version <number>", "Pull a specific version (requires agent IDs)").option("--no-tests", "Skip pulling test case definitions").action(pullCommand);
138344
138245
  program2.command("deploy [agentIds...]").description("Deploy local changes to Retell draft").option("-a, --all", "Deploy all agents in the account").option("-s, --select", "Force interactive agent selection").option("-n, --dry-run", "Show changes without applying").option("-v, --verbose", "Show full diff details (use with --dry-run)").option("-q, --quiet", "Output only affected agent IDs (for piping)").action(deployCommand);
138345
138246
  program2.command("publish [agentIds...]").description("Publish agents with unpublished draft changes").option("-a, --all", "Publish all agents in the account").option("-s, --select", "Force interactive agent selection").option("-n, --dry-run", "Show what would be published without publishing").option("-q, --quiet", "Output only published agent IDs (for piping)").action(publishCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retell-sync-cli",
3
- "version": "3.11.0",
3
+ "version": "3.13.0",
4
4
  "description": "CLI tool for syncing Retell AI agents between local filesystem and API",
5
5
  "keywords": [
6
6
  "agents",