retell-sync-cli 3.7.2 → 3.8.1
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/dist/cli.js +159 -10
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -98673,6 +98673,9 @@ function diff(obj, newObj, options = { cyclesFix: true }, _stack = []) {
|
|
|
98673
98673
|
return diffs;
|
|
98674
98674
|
}
|
|
98675
98675
|
|
|
98676
|
+
// src/commands/deploy.ts
|
|
98677
|
+
import path17 from "path";
|
|
98678
|
+
|
|
98676
98679
|
// node_modules/remeda/dist/lazyDataLastImpl-BDhrIOwR.js
|
|
98677
98680
|
function e(e2, t, n) {
|
|
98678
98681
|
let r = (n2) => e2(n2, ...t);
|
|
@@ -135140,19 +135143,15 @@ async function canonicalizeFromFiles(files) {
|
|
|
135140
135143
|
var InputMatchRuleSchema = zod_default.discriminatedUnion("type", [
|
|
135141
135144
|
zod_default.object({ type: zod_default.literal("any") }),
|
|
135142
135145
|
zod_default.object({
|
|
135143
|
-
type: zod_default.literal("
|
|
135144
|
-
|
|
135145
|
-
}),
|
|
135146
|
-
zod_default.object({
|
|
135147
|
-
type: zod_default.literal("partial"),
|
|
135148
|
-
input: zod_default.record(zod_default.string(), zod_default.unknown())
|
|
135146
|
+
type: zod_default.literal("partial_match"),
|
|
135147
|
+
args: zod_default.record(zod_default.string(), zod_default.unknown())
|
|
135149
135148
|
})
|
|
135150
135149
|
]);
|
|
135151
135150
|
var ToolMockSchema = zod_default.object({
|
|
135152
135151
|
tool_name: zod_default.string(),
|
|
135153
135152
|
input_match_rule: InputMatchRuleSchema,
|
|
135154
135153
|
output: zod_default.string(),
|
|
135155
|
-
result: zod_default.boolean()
|
|
135154
|
+
result: zod_default.boolean().nullable().optional()
|
|
135156
135155
|
});
|
|
135157
135156
|
var TestCaseResponseEngineSchema = zod_default.discriminatedUnion("type", [
|
|
135158
135157
|
zod_default.object({
|
|
@@ -135213,6 +135212,73 @@ async function getTestCaseDefinitions(responseEngine) {
|
|
|
135213
135212
|
}
|
|
135214
135213
|
return result.data;
|
|
135215
135214
|
}
|
|
135215
|
+
function canonicalizeTestCases(testCases) {
|
|
135216
|
+
return testCases.map(({ test_case_definition_id, response_engine: _10, ...rest }) => ({
|
|
135217
|
+
...rest,
|
|
135218
|
+
_id: test_case_definition_id
|
|
135219
|
+
}));
|
|
135220
|
+
}
|
|
135221
|
+
async function getLocalTestCases(agentDirPath) {
|
|
135222
|
+
const testsDir = path15.join(agentDirPath, "tests");
|
|
135223
|
+
const metaFile = Bun.file(path15.join(testsDir, ".tests.json"));
|
|
135224
|
+
if (!await metaFile.exists()) {
|
|
135225
|
+
return [];
|
|
135226
|
+
}
|
|
135227
|
+
const metaContent = await metaFile.text();
|
|
135228
|
+
const metadata = await readJson2(metaContent, zod_default.object({
|
|
135229
|
+
response_engine: zod_default.object({}).passthrough(),
|
|
135230
|
+
test_cases: zod_default.array(zod_default.object({
|
|
135231
|
+
id: zod_default.string(),
|
|
135232
|
+
name: zod_default.string()
|
|
135233
|
+
}))
|
|
135234
|
+
}));
|
|
135235
|
+
const testCases = [];
|
|
135236
|
+
for (const testCaseMeta of metadata.test_cases) {
|
|
135237
|
+
const testCaseName = toSnakeCase(testCaseMeta.name);
|
|
135238
|
+
let configContent = null;
|
|
135239
|
+
let reader = readYaml;
|
|
135240
|
+
for (const ext of ["yaml", "yml", "jsonc", "json"]) {
|
|
135241
|
+
const configPath = path15.join(testsDir, `${testCaseName}.${ext}`);
|
|
135242
|
+
const file2 = Bun.file(configPath);
|
|
135243
|
+
if (await file2.exists()) {
|
|
135244
|
+
configContent = await file2.text();
|
|
135245
|
+
reader = ext === "jsonc" ? readJsonc : ext === "json" ? readJson2 : readYaml;
|
|
135246
|
+
break;
|
|
135247
|
+
}
|
|
135248
|
+
}
|
|
135249
|
+
if (!configContent) {
|
|
135250
|
+
console.warn(`Warning: Could not find config file for test case ${testCaseMeta.name}`);
|
|
135251
|
+
continue;
|
|
135252
|
+
}
|
|
135253
|
+
const config2 = await reader(configContent, zod_default.looseObject({}));
|
|
135254
|
+
const resolveFileContent = async (filePath) => {
|
|
135255
|
+
const normalizedPath = filePath.replace(/^\.\//, "");
|
|
135256
|
+
const fullPath = path15.join(testsDir, normalizedPath);
|
|
135257
|
+
const content = await Bun.file(fullPath).text();
|
|
135258
|
+
return content;
|
|
135259
|
+
};
|
|
135260
|
+
await resolveFilePlaceholders(config2, resolveFileContent);
|
|
135261
|
+
testCases.push({
|
|
135262
|
+
...config2,
|
|
135263
|
+
_id: testCaseMeta.id
|
|
135264
|
+
});
|
|
135265
|
+
}
|
|
135266
|
+
return testCases;
|
|
135267
|
+
}
|
|
135268
|
+
async function updateTestCaseDefinition(testCaseId, update) {
|
|
135269
|
+
const response = await fetch(`https://api.retellai.com/update-test-case-definition/${testCaseId}`, {
|
|
135270
|
+
method: "PUT",
|
|
135271
|
+
headers: {
|
|
135272
|
+
Authorization: `Bearer ${process.env.RETELL_API_KEY}`,
|
|
135273
|
+
"Content-Type": "application/json"
|
|
135274
|
+
},
|
|
135275
|
+
body: JSON.stringify(update)
|
|
135276
|
+
});
|
|
135277
|
+
if (!response.ok) {
|
|
135278
|
+
const errorText = await response.text();
|
|
135279
|
+
throw new Error(`Failed to update test case ${testCaseId}: ${response.status} ${errorText}`);
|
|
135280
|
+
}
|
|
135281
|
+
}
|
|
135216
135282
|
async function fetchAndWriteTestCases({
|
|
135217
135283
|
state,
|
|
135218
135284
|
agentsDir = DEFAULT_AGENTS_DIR,
|
|
@@ -135806,10 +135872,78 @@ async function deploy({
|
|
|
135806
135872
|
const totalRemoteAgents = remoteState.voiceAgents.length + remoteState.chatAgents.length;
|
|
135807
135873
|
spinner.stop(source_default.dim(`Local: ${totalLocalAgents} agents | Remote: ${totalRemoteAgents} agents`));
|
|
135808
135874
|
spinner = createSpinner2("Computing differences...");
|
|
135809
|
-
const
|
|
135875
|
+
const baseChanges = computeChanges(localState, remoteState);
|
|
135876
|
+
const testCaseChanges = [];
|
|
135877
|
+
const allAgents = [
|
|
135878
|
+
...localState.voiceAgents.map((a7) => ({
|
|
135879
|
+
...a7,
|
|
135880
|
+
agentType: "voice"
|
|
135881
|
+
})),
|
|
135882
|
+
...localState.chatAgents.map((a7) => ({ ...a7, agentType: "chat" }))
|
|
135883
|
+
];
|
|
135884
|
+
for (const agent of allAgents) {
|
|
135885
|
+
if (agent.response_engine.type !== "retell-llm" && agent.response_engine.type !== "conversation-flow") {
|
|
135886
|
+
continue;
|
|
135887
|
+
}
|
|
135888
|
+
const agentName = agent.agent_name ?? agent._id;
|
|
135889
|
+
const hash2 = agent._id.slice(-FILE_HASH_LENGTH);
|
|
135890
|
+
const agentDirName = `${toSnakeCase(agentName)}_${hash2}`;
|
|
135891
|
+
const agentDirPath = path17.join(agentsDir, agentDirName);
|
|
135892
|
+
const localTestCases = await getLocalTestCases(agentDirPath);
|
|
135893
|
+
if (localTestCases.length === 0)
|
|
135894
|
+
continue;
|
|
135895
|
+
const normalizedEngine = agent.response_engine.type === "retell-llm" ? {
|
|
135896
|
+
type: "retell-llm",
|
|
135897
|
+
llm_id: agent.response_engine.llm_id,
|
|
135898
|
+
version: agent.response_engine.version ?? undefined
|
|
135899
|
+
} : {
|
|
135900
|
+
type: "conversation-flow",
|
|
135901
|
+
conversation_flow_id: agent.response_engine.conversation_flow_id,
|
|
135902
|
+
version: agent.response_engine.version ?? undefined
|
|
135903
|
+
};
|
|
135904
|
+
let remoteTestCases = [];
|
|
135905
|
+
try {
|
|
135906
|
+
const rawRemote = await getTestCaseDefinitions(normalizedEngine);
|
|
135907
|
+
remoteTestCases = canonicalizeTestCases(rawRemote);
|
|
135908
|
+
} catch {
|
|
135909
|
+
continue;
|
|
135910
|
+
}
|
|
135911
|
+
const testCaseMetadataFields = [
|
|
135912
|
+
"_id",
|
|
135913
|
+
"creation_timestamp",
|
|
135914
|
+
"user_modified_timestamp",
|
|
135915
|
+
"type"
|
|
135916
|
+
];
|
|
135917
|
+
const remoteTestCaseMap = new Map(remoteTestCases.map((tc3) => [tc3._id, tc3]));
|
|
135918
|
+
for (const localTC of localTestCases) {
|
|
135919
|
+
const remoteTC = remoteTestCaseMap.get(localTC._id);
|
|
135920
|
+
if (!remoteTC)
|
|
135921
|
+
continue;
|
|
135922
|
+
const normalizePrompt = (s5) => s5.trim().replace(/\r\n/g, `
|
|
135923
|
+
`);
|
|
135924
|
+
const localComparable = {
|
|
135925
|
+
...n9(localTC, testCaseMetadataFields),
|
|
135926
|
+
user_prompt: normalizePrompt(localTC.user_prompt)
|
|
135927
|
+
};
|
|
135928
|
+
const remoteComparable = {
|
|
135929
|
+
...n9(remoteTC, testCaseMetadataFields),
|
|
135930
|
+
user_prompt: normalizePrompt(remoteTC.user_prompt)
|
|
135931
|
+
};
|
|
135932
|
+
const differences = diff(remoteComparable, localComparable);
|
|
135933
|
+
if (differences.length > 0) {
|
|
135934
|
+
testCaseChanges.push({
|
|
135935
|
+
id: localTC._id,
|
|
135936
|
+
name: localTC.name,
|
|
135937
|
+
current: localTC,
|
|
135938
|
+
differences
|
|
135939
|
+
});
|
|
135940
|
+
}
|
|
135941
|
+
}
|
|
135942
|
+
}
|
|
135943
|
+
const changes = { ...baseChanges, testCases: testCaseChanges };
|
|
135810
135944
|
const totalAgentChanges = changes.voiceAgents.length + changes.chatAgents.length;
|
|
135811
|
-
spinner.stop(source_default.dim(`Found ${source_default.white(totalAgentChanges)} agent changes, ${source_default.white(changes.llms.length)} LLM changes, ${source_default.white(changes.flows.length)} flow changes`));
|
|
135812
|
-
const totalChanges = totalAgentChanges + changes.llms.length + changes.flows.length;
|
|
135945
|
+
spinner.stop(source_default.dim(`Found ${source_default.white(totalAgentChanges)} agent changes, ${source_default.white(changes.llms.length)} LLM changes, ${source_default.white(changes.flows.length)} flow changes, ${source_default.white(changes.testCases.length)} test case changes`));
|
|
135946
|
+
const totalChanges = totalAgentChanges + changes.llms.length + changes.flows.length + changes.testCases.length;
|
|
135813
135947
|
const affectedAgentIds = new Set;
|
|
135814
135948
|
for (const change of changes.voiceAgents) {
|
|
135815
135949
|
affectedAgentIds.add(change.id);
|
|
@@ -135869,6 +136003,11 @@ async function deploy({
|
|
|
135869
136003
|
const { _id, _version, ...updateData } = change.current;
|
|
135870
136004
|
await retell.conversationFlow.update(_id, updateData);
|
|
135871
136005
|
return { type: "flow", id: _id, name: change.name };
|
|
136006
|
+
}),
|
|
136007
|
+
...changes.testCases.map(async (change) => {
|
|
136008
|
+
const { _id, ...updateData } = change.current;
|
|
136009
|
+
await updateTestCaseDefinition(_id, updateData);
|
|
136010
|
+
return { type: "test case", id: _id, name: change.name };
|
|
135872
136011
|
})
|
|
135873
136012
|
]);
|
|
135874
136013
|
spinner.stop(source_default.dim("Done"));
|
|
@@ -136060,6 +136199,16 @@ Flows to update:`));
|
|
|
136060
136199
|
}
|
|
136061
136200
|
}
|
|
136062
136201
|
}
|
|
136202
|
+
if (changes.testCases.length > 0) {
|
|
136203
|
+
console.log(source_default.cyan(`
|
|
136204
|
+
Test cases to update:`));
|
|
136205
|
+
for (const change of changes.testCases) {
|
|
136206
|
+
console.log(` ${source_default.bold(change.name)} ${source_default.dim(`(${change.id})`)}`);
|
|
136207
|
+
for (const d5 of change.differences) {
|
|
136208
|
+
printDiff(d5, { verbose });
|
|
136209
|
+
}
|
|
136210
|
+
}
|
|
136211
|
+
}
|
|
136063
136212
|
}
|
|
136064
136213
|
|
|
136065
136214
|
// src/commands/publish.ts
|