retell-sync-cli 1.0.0 → 1.1.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 +76 -56
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -96621,6 +96621,9 @@ var require_dist = __commonJS((exports) => {
96621
96621
  exports.visitAsync = visit.visitAsync;
96622
96622
  });
96623
96623
 
96624
+ // src/cli.ts
96625
+ var {$: $13 } = globalThis.Bun;
96626
+
96624
96627
  // node_modules/commander/esm.mjs
96625
96628
  var import__ = __toESM(require_commander(), 1);
96626
96629
  var {
@@ -134612,19 +134615,13 @@ var dist_default3 = createPrompt((config2, done) => {
134612
134615
  var {$: $11 } = globalThis.Bun;
134613
134616
  async function pullCommand(opts, cmd) {
134614
134617
  const globalOpts = cmd.optsWithGlobals();
134615
- const {
134616
- branch = globalOpts.branch,
134617
- draft = false,
134618
- yes = false,
134619
- merge: merge2 = false
134620
- } = opts;
134621
134618
  try {
134622
134619
  await pull({
134623
134620
  agentsDir: globalOpts.agentsDir,
134624
- branch,
134625
- draft,
134626
- yes,
134627
- merge: merge2
134621
+ syncBranch: globalOpts.syncBranch,
134622
+ workingBranch: opts.merge ? globalOpts.workingBranch : undefined,
134623
+ draft: opts.draft,
134624
+ yes: opts.yes
134628
134625
  });
134629
134626
  } catch (err) {
134630
134627
  if (err instanceof ExitPromptError) {
@@ -134636,10 +134633,10 @@ async function pullCommand(opts, cmd) {
134636
134633
  }
134637
134634
  async function pull({
134638
134635
  agentsDir = DEFAULT_AGENTS_DIR,
134639
- branch,
134636
+ syncBranch,
134637
+ workingBranch,
134640
134638
  draft: pullDrafts = false,
134641
- yes: skipConfirmations = false,
134642
- merge: merge2 = false
134639
+ yes: skipConfirmations = false
134643
134640
  }) {
134644
134641
  if (pullDrafts && !skipConfirmations) {
134645
134642
  const proceed = await dist_default3({
@@ -134654,7 +134651,7 @@ async function pull({
134654
134651
  const remoteState = await getRemoteState({ draft: pullDrafts });
134655
134652
  spinner.stop(source_default.dim(`${pluralize("agent", remoteState.voiceAgents.length, true)}, ${pluralize("LLM", remoteState.llms.length, true)}, ${pluralize("flow", remoteState.conversationFlows.length, true)}`));
134656
134653
  const regressions = await checkVersionRegressions(remoteState.voiceAgents, {
134657
- branch,
134654
+ syncBranch,
134658
134655
  agentsDir
134659
134656
  });
134660
134657
  if (regressions.length > 0 && !skipConfirmations) {
@@ -134676,40 +134673,48 @@ Warning: ${regressions.length} agent(s) would have their version regressed:`));
134676
134673
  const files = await serializeState(remoteState, { agentsDir });
134677
134674
  spinner.stop(source_default.dim(`${pluralize("file", Object.keys(files).length, true)}`));
134678
134675
  spinner = createSpinner("Creating git objects...");
134679
- const result = await createCommitFromFiles(files, branch, {
134676
+ const result = await createCommitFromFiles(files, syncBranch, {
134680
134677
  agents: remoteState.voiceAgents.length,
134681
134678
  llms: remoteState.llms.length,
134682
134679
  flows: remoteState.conversationFlows.length
134683
134680
  });
134684
134681
  if (result.created) {
134685
- spinner.stop(source_default.green(`Updated ${source_default.bold(branch)} to ${source_default.yellow(result.commitSha.slice(0, 7))}`));
134682
+ spinner.stop(source_default.green(`Updated ${source_default.bold(syncBranch)} to ${source_default.yellow(result.commitSha.slice(0, 7))}`));
134686
134683
  } else {
134687
134684
  spinner.stop(source_default.dim(`No changes detected`));
134688
134685
  }
134689
- if (merge2) {
134690
- let targetBranch;
134691
- if (typeof merge2 === "string") {
134692
- targetBranch = merge2;
134686
+ if (workingBranch) {
134687
+ spinner = createSpinner(`Merging ${syncBranch} into ${workingBranch}...`);
134688
+ const { stdout: srcStdout } = await $11`git rev-parse refs/heads/${syncBranch}`.quiet();
134689
+ const srcSha = srcStdout.toString().trim();
134690
+ const { stdout: targetStdout, exitCode: targetExitCode } = await $11`git rev-parse refs/heads/${workingBranch} 2>/dev/null`.nothrow().quiet();
134691
+ if (targetExitCode !== 0) {
134692
+ await $11`git update-ref refs/heads/${workingBranch} ${srcSha}`.quiet();
134693
+ spinner.stop(source_default.green(`Created ${source_default.bold(workingBranch)} from ${source_default.bold(syncBranch)}`));
134693
134694
  } else {
134694
- const { stdout } = await $11`git rev-parse --abbrev-ref HEAD`.quiet();
134695
- targetBranch = stdout.toString().trim();
134696
- }
134697
- spinner = createSpinner(`Merging ${branch} into ${targetBranch}...`);
134698
- const {
134699
- exitCode,
134700
- stdout: mergeOut,
134701
- stderr
134702
- } = await $11`git merge ${branch} --allow-unrelated-histories --no-edit -m "Merge ${branch}"`.nothrow().quiet();
134703
- if (exitCode === 0) {
134704
- const alreadyUpToDate = mergeOut.toString().includes("Already up to date");
134705
- if (alreadyUpToDate) {
134695
+ const targetSha = targetStdout.toString().trim();
134696
+ if (srcSha === targetSha) {
134706
134697
  spinner.stop(source_default.dim(`Already up to date`));
134707
134698
  } else {
134708
- spinner.stop(source_default.green(`Merged ${source_default.bold(branch)} into ${source_default.bold(targetBranch)}`));
134699
+ const { exitCode: isAncestor } = await $11`git merge-base --is-ancestor ${targetSha} ${srcSha}`.nothrow().quiet();
134700
+ if (isAncestor === 0) {
134701
+ await $11`git update-ref refs/heads/${workingBranch} ${srcSha}`.quiet();
134702
+ spinner.stop(source_default.green(`Fast-forwarded ${source_default.bold(workingBranch)} to ${source_default.bold(syncBranch)}`));
134703
+ } else {
134704
+ const { stdout: mergeTreeOut, exitCode: mergeTreeExit } = await $11`git merge-tree --write-tree ${targetSha} ${srcSha}`.nothrow().quiet();
134705
+ if (mergeTreeExit !== 0) {
134706
+ spinner.stop(source_default.red(`Merge conflict`));
134707
+ console.error(source_default.red(`Cannot auto-merge ${syncBranch} into ${workingBranch}. Resolve conflicts manually.`));
134708
+ } else {
134709
+ const mergedTreeSha = mergeTreeOut.toString().trim();
134710
+ const message = `Merge ${syncBranch} into ${workingBranch}`;
134711
+ const { stdout: commitOut } = await $11`git commit-tree ${mergedTreeSha} -p ${targetSha} -p ${srcSha} -m ${message}`.quiet();
134712
+ const mergeCommitSha = commitOut.toString().trim();
134713
+ await $11`git update-ref refs/heads/${workingBranch} ${mergeCommitSha}`.quiet();
134714
+ spinner.stop(source_default.green(`Merged ${source_default.bold(syncBranch)} into ${source_default.bold(workingBranch)}`));
134715
+ }
134716
+ }
134709
134717
  }
134710
- } else {
134711
- spinner.stop(source_default.red(`Merge failed`));
134712
- console.error(source_default.red(stderr.toString()));
134713
134718
  }
134714
134719
  }
134715
134720
  }
@@ -134774,10 +134779,12 @@ async function createCommitFromFiles(files, branch, stats) {
134774
134779
  await $11`git update-ref refs/heads/${branch} ${commitSha}`.quiet();
134775
134780
  return { created: true, commitSha };
134776
134781
  }
134777
- async function checkVersionRegressions(remoteAgents, { branch, agentsDir }) {
134782
+ async function checkVersionRegressions(remoteAgents, { syncBranch, agentsDir }) {
134778
134783
  let branchState;
134779
134784
  try {
134780
- branchState = await getCommitState(`refs/heads/${branch}`, { agentsDir });
134785
+ branchState = await getCommitState(`refs/heads/${syncBranch}`, {
134786
+ agentsDir
134787
+ });
134781
134788
  } catch {
134782
134789
  return [];
134783
134790
  }
@@ -134800,15 +134807,15 @@ async function checkVersionRegressions(remoteAgents, { branch, agentsDir }) {
134800
134807
  // src/commands/deploy.ts
134801
134808
  async function deployCommand(opts, cmd) {
134802
134809
  const globalOpts = cmd.optsWithGlobals();
134803
- const { dryRun = false, draft = false, yes = false, publish = false } = opts;
134804
134810
  try {
134805
134811
  await deploy({
134806
134812
  agentsDir: globalOpts.agentsDir,
134807
- branch: globalOpts.branch,
134808
- dryRun,
134809
- draft,
134810
- yes,
134811
- publish
134813
+ syncBranch: globalOpts.syncBranch,
134814
+ workingBranch: globalOpts.workingBranch,
134815
+ dryRun: opts.dryRun,
134816
+ draft: opts.draft,
134817
+ yes: opts.yes,
134818
+ publish: opts.publish
134812
134819
  });
134813
134820
  } catch (err) {
134814
134821
  if (err instanceof ExitPromptError) {
@@ -134820,7 +134827,8 @@ async function deployCommand(opts, cmd) {
134820
134827
  }
134821
134828
  async function deploy({
134822
134829
  agentsDir = DEFAULT_AGENTS_DIR,
134823
- branch,
134830
+ syncBranch,
134831
+ workingBranch,
134824
134832
  dryRun = false,
134825
134833
  draft = false,
134826
134834
  yes = false,
@@ -134828,20 +134836,20 @@ async function deploy({
134828
134836
  }) {
134829
134837
  console.log(source_default.bold("Pulling first..."));
134830
134838
  await pull({
134831
- merge: true,
134839
+ syncBranch,
134840
+ workingBranch,
134832
134841
  draft,
134833
134842
  yes,
134834
- agentsDir,
134835
- branch
134843
+ agentsDir
134836
134844
  });
134837
134845
  console.log(source_default.bold("Analyzing changes..."));
134838
- const [{ stdout: headRef }, { stdout: syncRef }] = await Promise.all([
134839
- $12`git rev-parse HEAD`.quiet(),
134840
- $12`git rev-parse ${branch}`.quiet()
134846
+ const [{ stdout: workingRef }, { stdout: syncRef }] = await Promise.all([
134847
+ $12`git rev-parse refs/heads/${workingBranch}`.quiet(),
134848
+ $12`git rev-parse refs/heads/${syncBranch}`.quiet()
134841
134849
  ]);
134842
134850
  let spinner = createSpinner("Reading state from git...");
134843
134851
  const [currentState, syncState] = await Promise.all([
134844
- getCommitState(headRef.toString().trim(), { agentsDir }),
134852
+ getCommitState(workingRef.toString().trim(), { agentsDir }),
134845
134853
  getCommitState(syncRef.toString().trim(), { agentsDir })
134846
134854
  ]);
134847
134855
  spinner.stop(source_default.dim("Read state from git"));
@@ -134929,7 +134937,7 @@ async function deploy({
134929
134937
  draft,
134930
134938
  yes: true,
134931
134939
  agentsDir,
134932
- branch
134940
+ syncBranch
134933
134941
  });
134934
134942
  }
134935
134943
  }
@@ -135021,8 +135029,20 @@ function printChangeSummary(changes) {
135021
135029
 
135022
135030
  // src/cli.ts
135023
135031
  var program2 = new Command;
135024
- var DEFAULT_BRANCH = "retell-sync";
135025
- program2.name("retell").description("Retell AI agent management CLI").option("-w, --agents-dir <dir>", "Directory for agent files", DEFAULT_AGENTS_DIR).option("-b, --branch <branch>", "Git branch for sync", DEFAULT_BRANCH);
135026
- program2.command("pull").description("Pull agents from Retell API").option("-b, --branch <branch>", "Git branch for sync (overrides global)").option("-d, --draft", "Include unpublished agents").option("-y, --yes", "Skip confirmation prompts").option("-m, --merge [target]", "Merge sync branch into target (defaults to current branch)").action(pullCommand);
135032
+ var DEFAULT_SYNC_BRANCH = "retell-sync";
135033
+ async function getCurrentBranch() {
135034
+ const { stdout, exitCode } = await $13`git rev-parse --abbrev-ref HEAD`.nothrow().quiet();
135035
+ if (exitCode !== 0)
135036
+ return "HEAD";
135037
+ const branch = stdout.toString().trim();
135038
+ return branch === "HEAD" ? "HEAD" : branch;
135039
+ }
135040
+ program2.name("retell").description("Retell AI agent management CLI").option("-w, --agents-dir <dir>", "Directory for agent files", DEFAULT_AGENTS_DIR).option("-s, --sync-branch <branch>", "Branch for storing API state", DEFAULT_SYNC_BRANCH).option("-b, --working-branch <branch>", "Branch to merge into / compare against (defaults to current branch)").hook("preAction", async (thisCommand) => {
135041
+ const opts = thisCommand.opts();
135042
+ if (!opts.workingBranch) {
135043
+ opts.workingBranch = await getCurrentBranch();
135044
+ }
135045
+ });
135046
+ program2.command("pull").description("Pull agents from Retell API and optionally merge into working branch").option("-d, --draft", "Include unpublished agents").option("-y, --yes", "Skip confirmation prompts").option("-m, --merge", "Merge sync branch into working branch after pull").action(pullCommand);
135027
135047
  program2.command("deploy").description("Deploy local changes to Retell API").option("-n, --dry-run", "Show changes without applying").option("-d, --draft", "Include unpublished agents when pulling").option("-y, --yes", "Skip confirmation prompts").option("-p, --publish", "Publish agents after deploying").action(deployCommand);
135028
135048
  program2.parse();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "retell-sync-cli",
3
3
  "author": "zachsents",
4
- "version": "1.0.0",
4
+ "version": "1.1.0",
5
5
  "description": "CLI tool for syncing Retell AI agents between local filesystem and API",
6
6
  "type": "module",
7
7
  "main": "cli.ts",