retell-sync-cli 1.1.1 → 2.0.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 (3) hide show
  1. package/.todo +1 -0
  2. package/dist/cli.js +406 -18
  3. package/package.json +1 -1
package/.todo ADDED
@@ -0,0 +1 @@
1
+ - [ ] Make `deploy --publish` command update phone number to new agent version
package/dist/cli.js CHANGED
@@ -96638,7 +96638,11 @@ var {
96638
96638
  } = import__.default;
96639
96639
 
96640
96640
  // node_modules/@inquirer/core/dist/lib/key.js
96641
+ var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
96642
+ var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
96643
+ var isSpaceKey = (key) => key.name === "space";
96641
96644
  var isTabKey = (key) => key.name === "tab";
96645
+ var isNumberKey = (key) => "1234567890".includes(key.name);
96642
96646
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
96643
96647
  // node_modules/@inquirer/core/dist/lib/errors.js
96644
96648
  class AbortPromptError extends Error {
@@ -97175,6 +97179,18 @@ function usePrefix({ status = "idle", theme }) {
97175
97179
  const iconName = status === "loading" ? "idle" : status;
97176
97180
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
97177
97181
  }
97182
+ // node_modules/@inquirer/core/dist/lib/use-memo.js
97183
+ function useMemo(fn, dependencies) {
97184
+ return withPointer((pointer) => {
97185
+ const prev = pointer.get();
97186
+ if (!prev || prev.dependencies.length !== dependencies.length || prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
97187
+ const value = fn();
97188
+ pointer.set({ value, dependencies });
97189
+ return value;
97190
+ }
97191
+ return prev.value;
97192
+ });
97193
+ }
97178
97194
  // node_modules/@inquirer/core/dist/lib/use-ref.js
97179
97195
  function useRef(val) {
97180
97196
  return useState({ current: val })[0];
@@ -97647,6 +97663,72 @@ function readlineWidth() {
97647
97663
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
97648
97664
  }
97649
97665
 
97666
+ // node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
97667
+ function usePointerPosition({ active, renderedItems, pageSize, loop }) {
97668
+ const state = useRef({
97669
+ lastPointer: active,
97670
+ lastActive: undefined
97671
+ });
97672
+ const { lastPointer, lastActive } = state.current;
97673
+ const middle = Math.floor(pageSize / 2);
97674
+ const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
97675
+ const defaultPointerPosition = renderedItems.slice(0, active).reduce((acc, item) => acc + item.length, 0);
97676
+ let pointer = defaultPointerPosition;
97677
+ if (renderedLength > pageSize) {
97678
+ if (loop) {
97679
+ pointer = lastPointer;
97680
+ if (lastActive != null && lastActive < active && active - lastActive < pageSize) {
97681
+ pointer = Math.min(middle, Math.abs(active - lastActive) === 1 ? Math.min(lastPointer + (renderedItems[lastActive]?.length ?? 0), Math.max(defaultPointerPosition, lastPointer)) : lastPointer + active - lastActive);
97682
+ }
97683
+ } else {
97684
+ const spaceUnderActive = renderedItems.slice(active).reduce((acc, item) => acc + item.length, 0);
97685
+ pointer = spaceUnderActive < pageSize - middle ? pageSize - spaceUnderActive : Math.min(defaultPointerPosition, middle);
97686
+ }
97687
+ }
97688
+ state.current.lastPointer = pointer;
97689
+ state.current.lastActive = active;
97690
+ return pointer;
97691
+ }
97692
+ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
97693
+ const width = readlineWidth();
97694
+ const bound = (num) => (num % items.length + items.length) % items.length;
97695
+ const renderedItems = items.map((item, index) => {
97696
+ if (item == null)
97697
+ return [];
97698
+ return breakLines(renderItem({ item, index, isActive: index === active }), width).split(`
97699
+ `);
97700
+ });
97701
+ const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
97702
+ const renderItemAtIndex = (index) => renderedItems[index] ?? [];
97703
+ const pointer = usePointerPosition({ active, renderedItems, pageSize, loop });
97704
+ const activeItem = renderItemAtIndex(active).slice(0, pageSize);
97705
+ const activeItemPosition = pointer + activeItem.length <= pageSize ? pointer : pageSize - activeItem.length;
97706
+ const pageBuffer = Array.from({ length: pageSize });
97707
+ pageBuffer.splice(activeItemPosition, activeItem.length, ...activeItem);
97708
+ const itemVisited = new Set([active]);
97709
+ let bufferPointer = activeItemPosition + activeItem.length;
97710
+ let itemPointer = bound(active + 1);
97711
+ while (bufferPointer < pageSize && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer > active)) {
97712
+ const lines = renderItemAtIndex(itemPointer);
97713
+ const linesToAdd = lines.slice(0, pageSize - bufferPointer);
97714
+ pageBuffer.splice(bufferPointer, linesToAdd.length, ...linesToAdd);
97715
+ itemVisited.add(itemPointer);
97716
+ bufferPointer += linesToAdd.length;
97717
+ itemPointer = bound(itemPointer + 1);
97718
+ }
97719
+ bufferPointer = activeItemPosition - 1;
97720
+ itemPointer = bound(active - 1);
97721
+ while (bufferPointer >= 0 && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer < active)) {
97722
+ const lines = renderItemAtIndex(itemPointer);
97723
+ const linesToAdd = lines.slice(Math.max(0, lines.length - bufferPointer - 1));
97724
+ pageBuffer.splice(bufferPointer - linesToAdd.length + 1, linesToAdd.length, ...linesToAdd);
97725
+ itemVisited.add(itemPointer);
97726
+ bufferPointer -= linesToAdd.length;
97727
+ itemPointer = bound(itemPointer - 1);
97728
+ }
97729
+ return pageBuffer.filter((line) => typeof line === "string").join(`
97730
+ `);
97731
+ }
97650
97732
  // node_modules/@inquirer/core/dist/lib/create-prompt.js
97651
97733
  var import_mute_stream = __toESM(require_lib(), 1);
97652
97734
  import * as readline2 from "readline";
@@ -98043,6 +98125,20 @@ function createPrompt(view) {
98043
98125
  };
98044
98126
  return prompt;
98045
98127
  }
98128
+ // node_modules/@inquirer/core/dist/lib/Separator.js
98129
+ import { styleText as styleText2 } from "util";
98130
+ class Separator {
98131
+ separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
98132
+ type = "separator";
98133
+ constructor(separator) {
98134
+ if (separator) {
98135
+ this.separator = separator;
98136
+ }
98137
+ }
98138
+ static isSeparator(choice) {
98139
+ return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
98140
+ }
98141
+ }
98046
98142
  // node_modules/chalk/source/vendor/ansi-styles/index.js
98047
98143
  var ANSI_BACKGROUND_OFFSET2 = 10;
98048
98144
  var wrapAnsi162 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
@@ -134473,7 +134569,9 @@ async function writeJson(obj) {
134473
134569
  return formatWithPrettier(JSON.stringify(obj), { parser: "json" });
134474
134570
  }
134475
134571
  async function writeJsonc(obj, { comments = {} } = {}) {
134476
- const json2 = await formatWithPrettier(JSON.stringify(obj), { parser: "json" });
134572
+ const json2 = await formatWithPrettier(JSON.stringify(obj), {
134573
+ parser: "json"
134574
+ });
134477
134575
  if (Object.keys(comments).length === 0) {
134478
134576
  return json2;
134479
134577
  }
@@ -134615,14 +134713,19 @@ var retell = new retell_sdk_default({
134615
134713
  apiKey: process.env.RETELL_API_KEY
134616
134714
  });
134617
134715
  async function getRemoteState({
134618
- draft = false
134716
+ draft = false,
134717
+ agentIds = null
134619
134718
  } = {}) {
134620
134719
  const [allAgents, llms, conversationFlows] = await Promise.all([
134621
134720
  retellPagination((opts) => retell.agent.list(opts), "agent_id"),
134622
134721
  retellPagination((opts) => retell.llm.list(opts), "llm_id"),
134623
134722
  retellPagination((opts) => retell.conversationFlow.list(opts), "conversation_flow_id")
134624
134723
  ]);
134625
- const agents = draft ? allAgents : allAgents.filter((a7) => a7.is_published);
134724
+ let agents = draft ? allAgents : allAgents.filter((a7) => a7.is_published);
134725
+ if (agentIds) {
134726
+ const agentIdSet = new Set(agentIds);
134727
+ agents = agents.filter((a7) => agentIdSet.has(a7.agent_id));
134728
+ }
134626
134729
  return canonicalizeFromApi({ agents, llms, conversationFlows });
134627
134730
  }
134628
134731
  function canonicalizeFromApi({
@@ -134646,11 +134749,20 @@ function canonicalizeFromApi({
134646
134749
  };
134647
134750
  }
134648
134751
  async function getLocalState({
134649
- agentsDir = DEFAULT_AGENTS_DIR
134752
+ agentsDir = DEFAULT_AGENTS_DIR,
134753
+ agentIds = null
134650
134754
  } = {}) {
134651
134755
  const files = {};
134756
+ const agentIdSet = agentIds ? new Set(agentIds) : null;
134652
134757
  const agentIdGlob = new Bun.Glob("*/.agent.json");
134653
134758
  for await (const agentIdPath of agentIdGlob.scan(agentsDir)) {
134759
+ if (agentIdSet) {
134760
+ const metaContent = await Bun.file(path15.join(agentsDir, agentIdPath)).text();
134761
+ const meta3 = zod_default.object({ id: zod_default.string() }).safeParse(JSON.parse(metaContent));
134762
+ if (!meta3.success || !agentIdSet.has(meta3.data.id)) {
134763
+ continue;
134764
+ }
134765
+ }
134654
134766
  const agentDirName = path15.dirname(agentIdPath);
134655
134767
  const agentDirFull = path15.join(agentsDir, agentDirName);
134656
134768
  const filesGlob = new Bun.Glob("**/*");
@@ -134667,7 +134779,8 @@ async function getLocalState({
134667
134779
  }
134668
134780
  async function writeState(state, {
134669
134781
  agentsDir = DEFAULT_AGENTS_DIR,
134670
- configFormat = DEFAULT_CONFIG_FORMAT
134782
+ configFormat = DEFAULT_CONFIG_FORMAT,
134783
+ agentIds = null
134671
134784
  } = {}) {
134672
134785
  const files = await serializeState(state, { agentsDir, configFormat });
134673
134786
  const writtenFiles = new Set;
@@ -134678,12 +134791,25 @@ async function writeState(state, {
134678
134791
  writtenFiles.add(path15.relative(agentsDir, filePath));
134679
134792
  }
134680
134793
  const writtenDirs = new Set([...writtenFiles].map((f7) => f7.split(path15.sep)[0]).filter(Boolean));
134794
+ const managedAgentIds = agentIds ? new Set(agentIds) : null;
134681
134795
  const existingDirs = await fs8.readdir(agentsDir, { withFileTypes: true });
134682
134796
  for (const dirent of existingDirs) {
134683
134797
  if (!dirent.isDirectory())
134684
134798
  continue;
134685
134799
  const dirName = dirent.name;
134686
134800
  const dirPath = path15.join(agentsDir, dirName);
134801
+ if (managedAgentIds) {
134802
+ const metaPath = path15.join(dirPath, ".agent.json");
134803
+ const metaFile = Bun.file(metaPath);
134804
+ const metaExists = await metaFile.exists();
134805
+ if (metaExists) {
134806
+ const metaContent = await metaFile.text();
134807
+ const meta3 = zod_default.object({ id: zod_default.string() }).safeParse(JSON.parse(metaContent));
134808
+ if (!meta3.success || !managedAgentIds.has(meta3.data.id)) {
134809
+ continue;
134810
+ }
134811
+ }
134812
+ }
134687
134813
  if (!writtenDirs.has(dirName)) {
134688
134814
  await fs8.rm(dirPath, { recursive: true });
134689
134815
  } else {
@@ -134877,6 +135003,179 @@ async function canonicalizeFromFiles(files) {
134877
135003
  };
134878
135004
  }
134879
135005
 
135006
+ // node_modules/@inquirer/checkbox/dist/index.js
135007
+ import { styleText as styleText3 } from "util";
135008
+ var checkboxTheme = {
135009
+ icon: {
135010
+ checked: styleText3("green", dist_default.circleFilled),
135011
+ unchecked: dist_default.circle,
135012
+ cursor: dist_default.pointer
135013
+ },
135014
+ style: {
135015
+ disabledChoice: (text) => styleText3("dim", `- ${text}`),
135016
+ renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
135017
+ description: (text) => styleText3("cyan", text),
135018
+ keysHelpTip: (keys) => keys.map(([key2, action]) => `${styleText3("bold", key2)} ${styleText3("dim", action)}`).join(styleText3("dim", " \u2022 "))
135019
+ },
135020
+ keybindings: []
135021
+ };
135022
+ function isSelectable(item) {
135023
+ return !Separator.isSeparator(item) && !item.disabled;
135024
+ }
135025
+ function isChecked(item) {
135026
+ return isSelectable(item) && item.checked;
135027
+ }
135028
+ function toggle(item) {
135029
+ return isSelectable(item) ? { ...item, checked: !item.checked } : item;
135030
+ }
135031
+ function check3(checked2) {
135032
+ return function(item) {
135033
+ return isSelectable(item) ? { ...item, checked: checked2 } : item;
135034
+ };
135035
+ }
135036
+ function normalizeChoices(choices) {
135037
+ return choices.map((choice) => {
135038
+ if (Separator.isSeparator(choice))
135039
+ return choice;
135040
+ if (typeof choice === "string") {
135041
+ return {
135042
+ value: choice,
135043
+ name: choice,
135044
+ short: choice,
135045
+ checkedName: choice,
135046
+ disabled: false,
135047
+ checked: false
135048
+ };
135049
+ }
135050
+ const name = choice.name ?? String(choice.value);
135051
+ const normalizedChoice = {
135052
+ value: choice.value,
135053
+ name,
135054
+ short: choice.short ?? name,
135055
+ checkedName: choice.checkedName ?? name,
135056
+ disabled: choice.disabled ?? false,
135057
+ checked: choice.checked ?? false
135058
+ };
135059
+ if (choice.description) {
135060
+ normalizedChoice.description = choice.description;
135061
+ }
135062
+ return normalizedChoice;
135063
+ });
135064
+ }
135065
+ var dist_default3 = createPrompt((config2, done) => {
135066
+ const { pageSize = 7, loop = true, required: required2, validate: validate2 = () => true } = config2;
135067
+ const shortcuts = { all: "a", invert: "i", ...config2.shortcuts };
135068
+ const theme = makeTheme(checkboxTheme, config2.theme);
135069
+ const { keybindings } = theme;
135070
+ const [status, setStatus] = useState("idle");
135071
+ const prefix = usePrefix({ status, theme });
135072
+ const [items, setItems] = useState(normalizeChoices(config2.choices));
135073
+ const bounds = useMemo(() => {
135074
+ const first = items.findIndex(isSelectable);
135075
+ const last = items.findLastIndex(isSelectable);
135076
+ if (first === -1) {
135077
+ throw new ValidationError("[checkbox prompt] No selectable choices. All choices are disabled.");
135078
+ }
135079
+ return { first, last };
135080
+ }, [items]);
135081
+ const [active, setActive] = useState(bounds.first);
135082
+ const [errorMsg, setError] = useState();
135083
+ useKeypress(async (key2) => {
135084
+ if (isEnterKey(key2)) {
135085
+ const selection = items.filter(isChecked);
135086
+ const isValid = await validate2([...selection]);
135087
+ if (required2 && !items.some(isChecked)) {
135088
+ setError("At least one choice must be selected");
135089
+ } else if (isValid === true) {
135090
+ setStatus("done");
135091
+ done(selection.map((choice) => choice.value));
135092
+ } else {
135093
+ setError(isValid || "You must select a valid value");
135094
+ }
135095
+ } else if (isUpKey(key2, keybindings) || isDownKey(key2, keybindings)) {
135096
+ if (loop || isUpKey(key2, keybindings) && active !== bounds.first || isDownKey(key2, keybindings) && active !== bounds.last) {
135097
+ const offset = isUpKey(key2, keybindings) ? -1 : 1;
135098
+ let next = active;
135099
+ do {
135100
+ next = (next + offset + items.length) % items.length;
135101
+ } while (!isSelectable(items[next]));
135102
+ setActive(next);
135103
+ }
135104
+ } else if (isSpaceKey(key2)) {
135105
+ setError(undefined);
135106
+ setItems(items.map((choice, i5) => i5 === active ? toggle(choice) : choice));
135107
+ } else if (key2.name === shortcuts.all) {
135108
+ const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
135109
+ setItems(items.map(check3(selectAll)));
135110
+ } else if (key2.name === shortcuts.invert) {
135111
+ setItems(items.map(toggle));
135112
+ } else if (isNumberKey(key2)) {
135113
+ const selectedIndex = Number(key2.name) - 1;
135114
+ let selectableIndex = -1;
135115
+ const position = items.findIndex((item) => {
135116
+ if (Separator.isSeparator(item))
135117
+ return false;
135118
+ selectableIndex++;
135119
+ return selectableIndex === selectedIndex;
135120
+ });
135121
+ const selectedItem = items[position];
135122
+ if (selectedItem && isSelectable(selectedItem)) {
135123
+ setActive(position);
135124
+ setItems(items.map((choice, i5) => i5 === position ? toggle(choice) : choice));
135125
+ }
135126
+ }
135127
+ });
135128
+ const message = theme.style.message(config2.message, status);
135129
+ let description;
135130
+ const page = usePagination({
135131
+ items,
135132
+ active,
135133
+ renderItem({ item, isActive }) {
135134
+ if (Separator.isSeparator(item)) {
135135
+ return ` ${item.separator}`;
135136
+ }
135137
+ if (item.disabled) {
135138
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
135139
+ return theme.style.disabledChoice(`${item.name} ${disabledLabel}`);
135140
+ }
135141
+ if (isActive) {
135142
+ description = item.description;
135143
+ }
135144
+ const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
135145
+ const name = item.checked ? item.checkedName : item.name;
135146
+ const color = isActive ? theme.style.highlight : (x8) => x8;
135147
+ const cursor3 = isActive ? theme.icon.cursor : " ";
135148
+ return color(`${cursor3}${checkbox} ${name}`);
135149
+ },
135150
+ pageSize,
135151
+ loop
135152
+ });
135153
+ if (status === "done") {
135154
+ const selection = items.filter(isChecked);
135155
+ const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
135156
+ return [prefix, message, answer].filter(Boolean).join(" ");
135157
+ }
135158
+ const keys = [
135159
+ ["\u2191\u2193", "navigate"],
135160
+ ["space", "select"]
135161
+ ];
135162
+ if (shortcuts.all)
135163
+ keys.push([shortcuts.all, "all"]);
135164
+ if (shortcuts.invert)
135165
+ keys.push([shortcuts.invert, "invert"]);
135166
+ keys.push(["\u23CE", "submit"]);
135167
+ const helpLine = theme.style.keysHelpTip(keys);
135168
+ const lines = [
135169
+ [prefix, message].filter(Boolean).join(" "),
135170
+ page,
135171
+ " ",
135172
+ description ? theme.style.description(description) : "",
135173
+ errorMsg ? theme.style.error(errorMsg) : "",
135174
+ helpLine
135175
+ ].filter(Boolean).join(`
135176
+ `).trimEnd();
135177
+ return `${lines}${cursorHide}`;
135178
+ });
134880
135179
  // node_modules/@inquirer/confirm/dist/index.js
134881
135180
  function getBooleanValue(value, defaultValue) {
134882
135181
  let answer = defaultValue !== false;
@@ -134889,7 +135188,7 @@ function getBooleanValue(value, defaultValue) {
134889
135188
  function boolToString(value) {
134890
135189
  return value ? "Yes" : "No";
134891
135190
  }
134892
- var dist_default3 = createPrompt((config2, done) => {
135191
+ var dist_default4 = createPrompt((config2, done) => {
134893
135192
  const { transformer = boolToString } = config2;
134894
135193
  const [status, setStatus] = useState("idle");
134895
135194
  const [value, setValue] = useState("");
@@ -134922,14 +135221,94 @@ var dist_default3 = createPrompt((config2, done) => {
134922
135221
  const message = theme.style.message(config2.message, status);
134923
135222
  return `${prefix} ${message}${defaultValue} ${formattedValue}`;
134924
135223
  });
135224
+ // src/lib/sync-config.ts
135225
+ var SYNC_CONFIG_FILE = ".retell-sync.json";
135226
+ var syncConfigSchema = zod_default.object({
135227
+ agents: zod_default.array(zod_default.string()).optional()
135228
+ });
135229
+ async function readSyncConfig() {
135230
+ const file2 = Bun.file(SYNC_CONFIG_FILE);
135231
+ const exists = await file2.exists();
135232
+ if (!exists)
135233
+ return null;
135234
+ const content = await file2.text();
135235
+ const parsed = syncConfigSchema.safeParse(JSON.parse(content));
135236
+ if (!parsed.success) {
135237
+ console.warn(source_default.yellow(`Warning: Invalid ${SYNC_CONFIG_FILE} format, ignoring`));
135238
+ return null;
135239
+ }
135240
+ return parsed.data;
135241
+ }
135242
+ async function writeSyncConfig(config2) {
135243
+ const content = await writeJson(config2);
135244
+ await Bun.write(SYNC_CONFIG_FILE, content);
135245
+ }
135246
+ async function selectAgentsInteractive() {
135247
+ const agents = await retellPagination((opts) => retell.agent.list(opts), "agent_id");
135248
+ const agentMap = new Map;
135249
+ for (const agent of agents) {
135250
+ const existing = agentMap.get(agent.agent_id);
135251
+ if (!existing || (agent.version ?? 0) > (existing.version ?? 0)) {
135252
+ agentMap.set(agent.agent_id, agent);
135253
+ }
135254
+ }
135255
+ const uniqueAgents = [...agentMap.values()].sort((a7, b7) => (a7.agent_name ?? a7.agent_id).localeCompare(b7.agent_name ?? b7.agent_id));
135256
+ if (uniqueAgents.length === 0) {
135257
+ console.log(source_default.yellow("No agents found in the account"));
135258
+ return [];
135259
+ }
135260
+ const selected = await dist_default3({
135261
+ message: "Select agents to sync:",
135262
+ choices: uniqueAgents.map((agent) => ({
135263
+ name: agent.agent_name ?? agent.agent_id,
135264
+ value: agent.agent_id
135265
+ }))
135266
+ });
135267
+ if (selected.length === 0) {
135268
+ console.log(source_default.yellow("No agents selected"));
135269
+ return [];
135270
+ }
135271
+ const save = await dist_default4({
135272
+ message: `Save selection to ${SYNC_CONFIG_FILE}?`,
135273
+ default: true
135274
+ });
135275
+ if (save) {
135276
+ await writeSyncConfig({ agents: selected });
135277
+ console.log(source_default.dim(`Saved to ${SYNC_CONFIG_FILE}`));
135278
+ }
135279
+ return selected;
135280
+ }
135281
+ async function resolveAgentIds(args, { all = false, select = false } = {}) {
135282
+ if (select) {
135283
+ return selectAgentsInteractive();
135284
+ }
135285
+ if (args.length > 0) {
135286
+ return args;
135287
+ }
135288
+ if (all) {
135289
+ return null;
135290
+ }
135291
+ const config2 = await readSyncConfig();
135292
+ if (config2?.agents && config2.agents.length > 0) {
135293
+ console.log(source_default.dim(`Using ${config2.agents.length} agent(s) from ${SYNC_CONFIG_FILE}`));
135294
+ return config2.agents;
135295
+ }
135296
+ return selectAgentsInteractive();
135297
+ }
135298
+
134925
135299
  // src/commands/pull.ts
134926
135300
  var {$: $10 } = globalThis.Bun;
134927
- async function pullCommand(opts, cmd) {
135301
+ async function pullCommand(agentIdArgs, opts, cmd) {
134928
135302
  const globalOpts = cmd.optsWithGlobals();
134929
135303
  try {
135304
+ const agentIds = await resolveAgentIds(agentIdArgs, {
135305
+ all: opts.all,
135306
+ select: opts.select
135307
+ });
134930
135308
  await pull({
134931
135309
  agentsDir: globalOpts.agentsDir,
134932
135310
  configFormat: globalOpts.configFormat,
135311
+ agentIds,
134933
135312
  yes: opts.yes
134934
135313
  });
134935
135314
  } catch (err) {
@@ -134943,16 +135322,18 @@ async function pullCommand(opts, cmd) {
134943
135322
  async function pull({
134944
135323
  agentsDir = DEFAULT_AGENTS_DIR,
134945
135324
  configFormat = DEFAULT_CONFIG_FORMAT,
135325
+ agentIds = null,
134946
135326
  yes = false
134947
135327
  } = {}) {
134948
- console.log(source_default.bold("Pulling from Retell..."));
135328
+ const scopeLabel = agentIds ? `${agentIds.length} agent(s)` : "all agents";
135329
+ console.log(source_default.bold(`Pulling ${scopeLabel} from Retell...`));
134949
135330
  if (!yes) {
134950
135331
  const { stdout } = await $10`git status --porcelain -- ${agentsDir}`.nothrow().quiet();
134951
135332
  const hasChanges = stdout.toString().trim().length > 0;
134952
135333
  if (hasChanges) {
134953
135334
  console.log(source_default.yellow("Warning: You have uncommitted changes:"));
134954
135335
  console.log(source_default.dim(stdout.toString()));
134955
- const proceed = await dist_default3({
135336
+ const proceed = await dist_default4({
134956
135337
  message: "Pull will overwrite these files. Continue?",
134957
135338
  default: false
134958
135339
  });
@@ -134962,21 +135343,26 @@ async function pull({
134962
135343
  }
134963
135344
  }
134964
135345
  const spinner = createSpinner("Fetching from Retell API...");
134965
- const remoteState = await getRemoteState({ draft: true });
135346
+ const remoteState = await getRemoteState({ draft: true, agentIds });
134966
135347
  spinner.stop(source_default.dim(`${pluralize("agent", remoteState.voiceAgents.length, true)}, ${pluralize("LLM", remoteState.llms.length, true)}, ${pluralize("flow", remoteState.conversationFlows.length, true)}`));
134967
135348
  const writeSpinner = createSpinner("Writing files...");
134968
- await writeState(remoteState, { agentsDir, configFormat });
135349
+ await writeState(remoteState, { agentsDir, configFormat, agentIds });
134969
135350
  writeSpinner.stop(source_default.green("Done"));
134970
135351
  console.log(source_default.dim(`Files written to ${source_default.bold(agentsDir)}. Review with git diff.`));
134971
135352
  }
134972
135353
 
134973
135354
  // src/commands/deploy.ts
134974
- async function deployCommand(opts, cmd) {
135355
+ async function deployCommand(agentIdArgs, opts, cmd) {
134975
135356
  const globalOpts = cmd.optsWithGlobals();
134976
135357
  try {
135358
+ const agentIds = await resolveAgentIds(agentIdArgs, {
135359
+ all: opts.all,
135360
+ select: opts.select
135361
+ });
134977
135362
  await deploy({
134978
135363
  agentsDir: globalOpts.agentsDir,
134979
135364
  configFormat: globalOpts.configFormat,
135365
+ agentIds,
134980
135366
  dryRun: opts.dryRun,
134981
135367
  publish: opts.publish,
134982
135368
  verbose: opts.verbose
@@ -134992,16 +135378,18 @@ async function deployCommand(opts, cmd) {
134992
135378
  async function deploy({
134993
135379
  agentsDir = DEFAULT_AGENTS_DIR,
134994
135380
  configFormat = DEFAULT_CONFIG_FORMAT,
135381
+ agentIds = null,
134995
135382
  dryRun = false,
134996
135383
  publish = false,
134997
135384
  verbose = false
134998
135385
  } = {}) {
134999
- console.log(source_default.bold(publish ? "Deploying to Retell (will publish)..." : "Deploying to Retell..."));
135386
+ const scopeLabel = agentIds ? `${agentIds.length} agent(s)` : "all agents";
135387
+ console.log(source_default.bold(publish ? `Deploying ${scopeLabel} to Retell (will publish)...` : `Deploying ${scopeLabel} to Retell...`));
135000
135388
  console.log(source_default.bold("Analyzing changes..."));
135001
135389
  let spinner = createSpinner("Reading local and remote state...");
135002
135390
  const [localState, remoteState] = await Promise.all([
135003
- getLocalState({ agentsDir }),
135004
- getRemoteState({ draft: true })
135391
+ getLocalState({ agentsDir, agentIds }),
135392
+ getRemoteState({ draft: true, agentIds })
135005
135393
  ]);
135006
135394
  spinner.stop(source_default.dim(`Local: ${localState.voiceAgents.length} agents | Remote: ${remoteState.voiceAgents.length} agents`));
135007
135395
  spinner = createSpinner("Computing differences...");
@@ -135083,7 +135471,7 @@ async function deploy({
135083
135471
  console.log(source_default.green(`Published ${pluralize("agent", publishedCount, true)}`));
135084
135472
  }
135085
135473
  console.log(source_default.bold("Syncing latest state..."));
135086
- await pull({ agentsDir, configFormat });
135474
+ await pull({ agentsDir, configFormat, agentIds });
135087
135475
  }
135088
135476
  function computeChanges(local, remote) {
135089
135477
  const changes = {
@@ -135225,6 +135613,6 @@ Flows to update:`));
135225
135613
  // src/cli.ts
135226
135614
  var program2 = new Command;
135227
135615
  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);
135228
- program2.command("pull").description("Pull agents from Retell API (always pulls latest draft state)").option("-y, --yes", "Skip confirmation prompts").action(pullCommand);
135229
- program2.command("deploy").description("Deploy local changes to Retell API").option("-n, --dry-run", "Show changes without applying").option("-p, --publish", "Publish changed agents after deploying").option("-v, --verbose", "Show full diff details (use with --dry-run)").action(deployCommand);
135616
+ program2.command("pull [agentIds...]").description("Pull agents from Retell API (always pulls latest draft state)").option("-a, --all", "Pull all agents in the account").option("-s, --select", "Force interactive agent selection").option("-y, --yes", "Skip confirmation prompts").action(pullCommand);
135617
+ program2.command("deploy [agentIds...]").description("Deploy local changes to Retell API").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("-p, --publish", "Publish changed agents after deploying").option("-v, --verbose", "Show full diff details (use with --dry-run)").action(deployCommand);
135230
135618
  program2.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retell-sync-cli",
3
- "version": "1.1.1",
3
+ "version": "2.0.0",
4
4
  "description": "CLI tool for syncing Retell AI agents between local filesystem and API",
5
5
  "keywords": [
6
6
  "agents",