retell-sync-cli 1.1.1 → 2.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.
- package/.todo +1 -0
- package/dist/cli.js +482 -21
- package/package.json +3 -2
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), {
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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...");
|
|
@@ -135071,19 +135459,92 @@ async function deploy({
|
|
|
135071
135459
|
return { id: id2, name: agentNames.get(id2) ?? id2 };
|
|
135072
135460
|
}));
|
|
135073
135461
|
spinner.stop(source_default.dim("Done"));
|
|
135074
|
-
|
|
135462
|
+
const publishedAgentIds = [];
|
|
135075
135463
|
for (const result of publishResults) {
|
|
135076
135464
|
if (result.status === "fulfilled") {
|
|
135077
135465
|
console.log(source_default.green(`Published ${source_default.bold(result.value.name)}`));
|
|
135078
|
-
|
|
135466
|
+
publishedAgentIds.push(result.value.id);
|
|
135079
135467
|
} else {
|
|
135080
135468
|
console.log(source_default.red(`Failed to publish: ${result.reason}`));
|
|
135081
135469
|
}
|
|
135082
135470
|
}
|
|
135083
|
-
console.log(source_default.green(`Published ${pluralize("agent",
|
|
135471
|
+
console.log(source_default.green(`Published ${pluralize("agent", publishedAgentIds.length, true)}`));
|
|
135472
|
+
if (publishedAgentIds.length > 0) {
|
|
135473
|
+
await updatePhoneNumberVersions(publishedAgentIds, agentNames);
|
|
135474
|
+
}
|
|
135084
135475
|
}
|
|
135085
135476
|
console.log(source_default.bold("Syncing latest state..."));
|
|
135086
|
-
await pull({ agentsDir, configFormat });
|
|
135477
|
+
await pull({ agentsDir, configFormat, agentIds });
|
|
135478
|
+
}
|
|
135479
|
+
async function updatePhoneNumberVersions(publishedAgentIds, agentNames) {
|
|
135480
|
+
const spinner = createSpinner("Updating phone numbers...");
|
|
135481
|
+
const [phoneNumbers, ...agentVersionLists] = await Promise.all([
|
|
135482
|
+
retell.phoneNumber.list(),
|
|
135483
|
+
...publishedAgentIds.map((id2) => retell.agent.getVersions(id2))
|
|
135484
|
+
]);
|
|
135485
|
+
const publishedVersions = new Map;
|
|
135486
|
+
for (const [i5, agentId] of publishedAgentIds.entries()) {
|
|
135487
|
+
const versions2 = agentVersionLists[i5];
|
|
135488
|
+
if (!versions2)
|
|
135489
|
+
continue;
|
|
135490
|
+
const latestPublished = versions2.filter((v10) => v10.is_published).sort((a7, b7) => (b7.version ?? 0) - (a7.version ?? 0))[0];
|
|
135491
|
+
if (latestPublished?.version != null) {
|
|
135492
|
+
publishedVersions.set(agentId, latestPublished.version);
|
|
135493
|
+
}
|
|
135494
|
+
}
|
|
135495
|
+
const publishedAgentIdSet = new Set(publishedAgentIds);
|
|
135496
|
+
const updates = [];
|
|
135497
|
+
for (const phone of phoneNumbers) {
|
|
135498
|
+
const inboundVersion = phone.inbound_agent_id && publishedAgentIdSet.has(phone.inbound_agent_id) ? publishedVersions.get(phone.inbound_agent_id) : undefined;
|
|
135499
|
+
const outboundVersion = phone.outbound_agent_id && publishedAgentIdSet.has(phone.outbound_agent_id) ? publishedVersions.get(phone.outbound_agent_id) : undefined;
|
|
135500
|
+
if (inboundVersion != null || outboundVersion != null) {
|
|
135501
|
+
updates.push({
|
|
135502
|
+
phoneNumber: phone.phone_number,
|
|
135503
|
+
inboundVersion,
|
|
135504
|
+
outboundVersion
|
|
135505
|
+
});
|
|
135506
|
+
}
|
|
135507
|
+
}
|
|
135508
|
+
if (updates.length === 0) {
|
|
135509
|
+
spinner.stop(source_default.dim("No phone numbers to update"));
|
|
135510
|
+
return;
|
|
135511
|
+
}
|
|
135512
|
+
const updateResults = await Promise.allSettled(updates.map(async ({ phoneNumber, inboundVersion, outboundVersion }) => {
|
|
135513
|
+
await retell.phoneNumber.update(phoneNumber, {
|
|
135514
|
+
...inboundVersion != null && {
|
|
135515
|
+
inbound_agent_version: inboundVersion
|
|
135516
|
+
},
|
|
135517
|
+
...outboundVersion != null && {
|
|
135518
|
+
outbound_agent_version: outboundVersion
|
|
135519
|
+
}
|
|
135520
|
+
});
|
|
135521
|
+
return phoneNumber;
|
|
135522
|
+
}));
|
|
135523
|
+
spinner.stop(source_default.dim("Done"));
|
|
135524
|
+
let updatedCount = 0;
|
|
135525
|
+
for (const result of updateResults) {
|
|
135526
|
+
if (result.status === "fulfilled") {
|
|
135527
|
+
const phone = updates.find((u4) => u4.phoneNumber === result.value);
|
|
135528
|
+
const agentInfo = [];
|
|
135529
|
+
if (phone?.inboundVersion != null) {
|
|
135530
|
+
const inboundPhone = phoneNumbers.find((p4) => p4.phone_number === result.value);
|
|
135531
|
+
const agentId = inboundPhone?.inbound_agent_id;
|
|
135532
|
+
const name = agentId ? agentNames.get(agentId) ?? agentId : "unknown";
|
|
135533
|
+
agentInfo.push(`inbound: ${name} v${phone.inboundVersion}`);
|
|
135534
|
+
}
|
|
135535
|
+
if (phone?.outboundVersion != null) {
|
|
135536
|
+
const outboundPhone = phoneNumbers.find((p4) => p4.phone_number === result.value);
|
|
135537
|
+
const agentId = outboundPhone?.outbound_agent_id;
|
|
135538
|
+
const name = agentId ? agentNames.get(agentId) ?? agentId : "unknown";
|
|
135539
|
+
agentInfo.push(`outbound: ${name} v${phone.outboundVersion}`);
|
|
135540
|
+
}
|
|
135541
|
+
console.log(source_default.green(`Updated ${source_default.bold(result.value)} (${agentInfo.join(", ")})`));
|
|
135542
|
+
updatedCount++;
|
|
135543
|
+
} else {
|
|
135544
|
+
console.log(source_default.red(`Failed to update phone number: ${result.reason}`));
|
|
135545
|
+
}
|
|
135546
|
+
}
|
|
135547
|
+
console.log(source_default.green(`Updated ${pluralize("phone number", updatedCount, true)}`));
|
|
135087
135548
|
}
|
|
135088
135549
|
function computeChanges(local, remote) {
|
|
135089
135550
|
const changes = {
|
|
@@ -135225,6 +135686,6 @@ Flows to update:`));
|
|
|
135225
135686
|
// src/cli.ts
|
|
135226
135687
|
var program2 = new Command;
|
|
135227
135688
|
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);
|
|
135689
|
+
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);
|
|
135690
|
+
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
135691
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "retell-sync-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "CLI tool for syncing Retell AI agents between local filesystem and API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"check": "bunx tsc --noEmit && bun fix",
|
|
20
20
|
"fix": "oxlint --type-aware --fix-suggestions && prettier . --write",
|
|
21
|
-
"build": "bun build ./src/cli.ts --target bun --outdir dist"
|
|
21
|
+
"build": "bun check && bun build ./src/cli.ts --target bun --outdir dist",
|
|
22
|
+
"prepublishOnly": "bun run build"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"@inquirer/prompts": "^8.1.0",
|