retell-sync-cli 3.6.0 → 3.7.2
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 +204 -3
- package/package.json +1 -1
- package/.env.local +0 -1
- package/.oxlintrc.json +0 -12
- package/.prettierrc.json +0 -7
- package/.vscode/settings.json +0 -9
- package/test/raw-agents-list-response.json +0 -7264
- package/test/raw-conversation-flow-list-response.json +0 -56946
- package/test/raw-llms-list-response.json +0 -29782
- package/tsconfig.json +0 -29
package/dist/cli.js
CHANGED
|
@@ -135137,6 +135137,194 @@ async function canonicalizeFromFiles(files) {
|
|
|
135137
135137
|
conversationFlows
|
|
135138
135138
|
};
|
|
135139
135139
|
}
|
|
135140
|
+
var InputMatchRuleSchema = zod_default.discriminatedUnion("type", [
|
|
135141
|
+
zod_default.object({ type: zod_default.literal("any") }),
|
|
135142
|
+
zod_default.object({
|
|
135143
|
+
type: zod_default.literal("exact"),
|
|
135144
|
+
input: zod_default.record(zod_default.string(), zod_default.unknown())
|
|
135145
|
+
}),
|
|
135146
|
+
zod_default.object({
|
|
135147
|
+
type: zod_default.literal("partial"),
|
|
135148
|
+
input: zod_default.record(zod_default.string(), zod_default.unknown())
|
|
135149
|
+
})
|
|
135150
|
+
]);
|
|
135151
|
+
var ToolMockSchema = zod_default.object({
|
|
135152
|
+
tool_name: zod_default.string(),
|
|
135153
|
+
input_match_rule: InputMatchRuleSchema,
|
|
135154
|
+
output: zod_default.string(),
|
|
135155
|
+
result: zod_default.boolean()
|
|
135156
|
+
});
|
|
135157
|
+
var TestCaseResponseEngineSchema = zod_default.discriminatedUnion("type", [
|
|
135158
|
+
zod_default.object({
|
|
135159
|
+
type: zod_default.literal("retell-llm"),
|
|
135160
|
+
llm_id: zod_default.string(),
|
|
135161
|
+
version: zod_default.number().optional()
|
|
135162
|
+
}),
|
|
135163
|
+
zod_default.object({
|
|
135164
|
+
type: zod_default.literal("conversation-flow"),
|
|
135165
|
+
conversation_flow_id: zod_default.string(),
|
|
135166
|
+
version: zod_default.number().optional()
|
|
135167
|
+
})
|
|
135168
|
+
]);
|
|
135169
|
+
var TestCaseDefinitionSchema = zod_default.object({
|
|
135170
|
+
test_case_definition_id: zod_default.string(),
|
|
135171
|
+
name: zod_default.string(),
|
|
135172
|
+
response_engine: TestCaseResponseEngineSchema,
|
|
135173
|
+
dynamic_variables: zod_default.record(zod_default.string(), zod_default.unknown()).optional().default({}),
|
|
135174
|
+
metrics: zod_default.array(zod_default.string()).optional().default([]),
|
|
135175
|
+
user_prompt: zod_default.string(),
|
|
135176
|
+
creation_timestamp: zod_default.number(),
|
|
135177
|
+
user_modified_timestamp: zod_default.number(),
|
|
135178
|
+
type: zod_default.literal("simulation"),
|
|
135179
|
+
tool_mocks: zod_default.array(ToolMockSchema).optional().default([]),
|
|
135180
|
+
llm_model: zod_default.string()
|
|
135181
|
+
});
|
|
135182
|
+
async function getTestCaseDefinitions(responseEngine) {
|
|
135183
|
+
const params = new URLSearchParams({ type: responseEngine.type });
|
|
135184
|
+
if (responseEngine.type === "retell-llm") {
|
|
135185
|
+
params.set("llm_id", responseEngine.llm_id);
|
|
135186
|
+
if (responseEngine.version != null) {
|
|
135187
|
+
params.set("version", String(responseEngine.version));
|
|
135188
|
+
}
|
|
135189
|
+
} else {
|
|
135190
|
+
params.set("conversation_flow_id", responseEngine.conversation_flow_id);
|
|
135191
|
+
if (responseEngine.version != null) {
|
|
135192
|
+
params.set("version", String(responseEngine.version));
|
|
135193
|
+
}
|
|
135194
|
+
}
|
|
135195
|
+
const response = await fetch(`https://api.retellai.com/list-test-case-definitions?${params.toString()}`, {
|
|
135196
|
+
headers: {
|
|
135197
|
+
Authorization: `Bearer ${process.env.RETELL_API_KEY}`,
|
|
135198
|
+
"Content-Type": "application/json"
|
|
135199
|
+
}
|
|
135200
|
+
});
|
|
135201
|
+
if (!response.ok) {
|
|
135202
|
+
const errorText = await response.text();
|
|
135203
|
+
if (response.status === 404) {
|
|
135204
|
+
return [];
|
|
135205
|
+
}
|
|
135206
|
+
throw new Error(`Failed to fetch test cases: ${response.status} ${errorText}`);
|
|
135207
|
+
}
|
|
135208
|
+
const data = await response.json();
|
|
135209
|
+
const result = zod_default.array(TestCaseDefinitionSchema).safeParse(data);
|
|
135210
|
+
if (!result.success) {
|
|
135211
|
+
console.warn("Warning: Some test case fields failed validation:", result.error.issues);
|
|
135212
|
+
return [];
|
|
135213
|
+
}
|
|
135214
|
+
return result.data;
|
|
135215
|
+
}
|
|
135216
|
+
async function fetchAndWriteTestCases({
|
|
135217
|
+
state,
|
|
135218
|
+
agentsDir = DEFAULT_AGENTS_DIR,
|
|
135219
|
+
configFormat = DEFAULT_CONFIG_FORMAT
|
|
135220
|
+
}) {
|
|
135221
|
+
const results = [];
|
|
135222
|
+
const allAgents = [
|
|
135223
|
+
...state.voiceAgents.map((a7) => ({
|
|
135224
|
+
...a7,
|
|
135225
|
+
agentType: "voice"
|
|
135226
|
+
})),
|
|
135227
|
+
...state.chatAgents.map((a7) => ({
|
|
135228
|
+
...a7,
|
|
135229
|
+
agentType: "chat"
|
|
135230
|
+
}))
|
|
135231
|
+
];
|
|
135232
|
+
for (const agent of allAgents) {
|
|
135233
|
+
const agentName = agent.agent_name ?? agent._id;
|
|
135234
|
+
const hash2 = agent._id.slice(-FILE_HASH_LENGTH);
|
|
135235
|
+
const agentDirName = `${toSnakeCase(agentName)}_${hash2}`;
|
|
135236
|
+
const agentDirPath = path15.join(agentsDir, agentDirName);
|
|
135237
|
+
if (agent.response_engine.type !== "retell-llm" && agent.response_engine.type !== "conversation-flow") {
|
|
135238
|
+
continue;
|
|
135239
|
+
}
|
|
135240
|
+
const normalizedEngine = agent.response_engine.type === "retell-llm" ? {
|
|
135241
|
+
type: "retell-llm",
|
|
135242
|
+
llm_id: agent.response_engine.llm_id,
|
|
135243
|
+
version: agent.response_engine.version ?? undefined
|
|
135244
|
+
} : {
|
|
135245
|
+
type: "conversation-flow",
|
|
135246
|
+
conversation_flow_id: agent.response_engine.conversation_flow_id,
|
|
135247
|
+
version: agent.response_engine.version ?? undefined
|
|
135248
|
+
};
|
|
135249
|
+
let testCases;
|
|
135250
|
+
try {
|
|
135251
|
+
testCases = await getTestCaseDefinitions(normalizedEngine);
|
|
135252
|
+
} catch (err) {
|
|
135253
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
135254
|
+
console.warn(`Warning: Could not fetch test cases for ${agentName}: ${message}`);
|
|
135255
|
+
continue;
|
|
135256
|
+
}
|
|
135257
|
+
if (testCases.length === 0) {
|
|
135258
|
+
const testsDir = path15.join(agentDirPath, "tests");
|
|
135259
|
+
await fs8.rm(testsDir, { recursive: true, force: true }).catch(() => {});
|
|
135260
|
+
continue;
|
|
135261
|
+
}
|
|
135262
|
+
await writeTestCases(testCases, {
|
|
135263
|
+
agentDirPath,
|
|
135264
|
+
responseEngine: normalizedEngine,
|
|
135265
|
+
configFormat
|
|
135266
|
+
});
|
|
135267
|
+
results.push({ agentDir: agentDirName, testCount: testCases.length });
|
|
135268
|
+
}
|
|
135269
|
+
return results;
|
|
135270
|
+
}
|
|
135271
|
+
async function writeTestCases(testCases, {
|
|
135272
|
+
agentDirPath,
|
|
135273
|
+
responseEngine,
|
|
135274
|
+
configFormat = DEFAULT_CONFIG_FORMAT
|
|
135275
|
+
}) {
|
|
135276
|
+
const testsDir = path15.join(agentDirPath, "tests");
|
|
135277
|
+
await fs8.mkdir(testsDir, { recursive: true });
|
|
135278
|
+
const isYaml = configFormat === "yaml" || configFormat === "yml";
|
|
135279
|
+
const isJsonc = configFormat === "jsonc";
|
|
135280
|
+
const configExt = configFormat;
|
|
135281
|
+
const metadata = {
|
|
135282
|
+
response_engine: responseEngine,
|
|
135283
|
+
test_cases: testCases.map((tc3) => ({
|
|
135284
|
+
id: tc3.test_case_definition_id,
|
|
135285
|
+
name: tc3.name
|
|
135286
|
+
}))
|
|
135287
|
+
};
|
|
135288
|
+
await Bun.write(path15.join(testsDir, ".tests.json"), await writeJson(metadata));
|
|
135289
|
+
const writtenFiles = new Set([".tests.json"]);
|
|
135290
|
+
for (const testCase of testCases) {
|
|
135291
|
+
const {
|
|
135292
|
+
test_case_definition_id: _id,
|
|
135293
|
+
response_engine: _engine,
|
|
135294
|
+
creation_timestamp: _created,
|
|
135295
|
+
user_modified_timestamp: _modified,
|
|
135296
|
+
type: _type,
|
|
135297
|
+
...config2
|
|
135298
|
+
} = testCase;
|
|
135299
|
+
const testCaseName = toSnakeCase(testCase.name);
|
|
135300
|
+
const promptFileName = `${testCaseName}_prompt.md`;
|
|
135301
|
+
const promptFilePath = path15.join(testsDir, promptFileName);
|
|
135302
|
+
await Bun.write(promptFilePath, await writeMarkdown(config2.user_prompt));
|
|
135303
|
+
writtenFiles.add(promptFileName);
|
|
135304
|
+
const configWithFileRef = {
|
|
135305
|
+
...config2,
|
|
135306
|
+
user_prompt: `file://./${promptFileName}`
|
|
135307
|
+
};
|
|
135308
|
+
const configFileName = `${testCaseName}.${configExt}`;
|
|
135309
|
+
const configContent = isYaml ? await writeYaml(configWithFileRef, { comments: testCaseFieldDocs }) : isJsonc ? await writeJsonc(configWithFileRef, { comments: testCaseFieldDocs }) : await writeJson(configWithFileRef);
|
|
135310
|
+
await Bun.write(path15.join(testsDir, configFileName), configContent);
|
|
135311
|
+
writtenFiles.add(configFileName);
|
|
135312
|
+
}
|
|
135313
|
+
const existingFiles = await fs8.readdir(testsDir).catch(() => []);
|
|
135314
|
+
for (const file2 of existingFiles) {
|
|
135315
|
+
if (!writtenFiles.has(file2)) {
|
|
135316
|
+
await fs8.rm(path15.join(testsDir, file2)).catch(() => {});
|
|
135317
|
+
}
|
|
135318
|
+
}
|
|
135319
|
+
}
|
|
135320
|
+
var testCaseFieldDocs = {
|
|
135321
|
+
name: "Name of the test case",
|
|
135322
|
+
user_prompt: "Prompt describing simulated user behavior (file reference)",
|
|
135323
|
+
metrics: "Array of evaluation criteria to check",
|
|
135324
|
+
dynamic_variables: "Variables injected into the agent during test",
|
|
135325
|
+
tool_mocks: "Mock responses for tool/function calls",
|
|
135326
|
+
llm_model: "LLM model used to simulate the user"
|
|
135327
|
+
};
|
|
135140
135328
|
|
|
135141
135329
|
// src/lib/logger.ts
|
|
135142
135330
|
var quietMode = false;
|
|
@@ -135515,7 +135703,8 @@ async function pullCommand(agentIdArgs, opts, cmd) {
|
|
|
135515
135703
|
agentsDir: globalOpts.agentsDir,
|
|
135516
135704
|
configFormat: globalOpts.configFormat,
|
|
135517
135705
|
agentIds,
|
|
135518
|
-
yes: opts.yes
|
|
135706
|
+
yes: opts.yes,
|
|
135707
|
+
tests: opts.tests ?? true
|
|
135519
135708
|
});
|
|
135520
135709
|
} catch (err) {
|
|
135521
135710
|
if (err instanceof ExitPromptError) {
|
|
@@ -135529,7 +135718,8 @@ async function pull({
|
|
|
135529
135718
|
agentsDir = DEFAULT_AGENTS_DIR,
|
|
135530
135719
|
configFormat = DEFAULT_CONFIG_FORMAT,
|
|
135531
135720
|
agentIds = null,
|
|
135532
|
-
yes = false
|
|
135721
|
+
yes = false,
|
|
135722
|
+
tests = true
|
|
135533
135723
|
} = {}) {
|
|
135534
135724
|
const scopeLabel = agentIds ? `${agentIds.length} agent(s)` : "all agents";
|
|
135535
135725
|
console.log(source_default.bold(`Pulling ${scopeLabel} from Retell...`));
|
|
@@ -135555,6 +135745,17 @@ async function pull({
|
|
|
135555
135745
|
const writeSpinner = createSpinner("Writing files...");
|
|
135556
135746
|
await writeState(remoteState, { agentsDir, configFormat, agentIds });
|
|
135557
135747
|
writeSpinner.stop(source_default.green("Done"));
|
|
135748
|
+
if (tests) {
|
|
135749
|
+
const testSpinner = createSpinner("Fetching test cases...");
|
|
135750
|
+
const testResults = await fetchAndWriteTestCases({
|
|
135751
|
+
state: remoteState,
|
|
135752
|
+
agentsDir,
|
|
135753
|
+
configFormat
|
|
135754
|
+
});
|
|
135755
|
+
const totalTests = testResults.reduce((sum, r10) => sum + r10.testCount, 0);
|
|
135756
|
+
const agentsWithTests = testResults.filter((r10) => r10.testCount > 0).length;
|
|
135757
|
+
testSpinner.stop(source_default.dim(`${pluralize("test case", totalTests, true)} across ${pluralize("agent", agentsWithTests, true)}`));
|
|
135758
|
+
}
|
|
135558
135759
|
console.log(source_default.dim(`Files written to ${source_default.bold(agentsDir)}. Review with git diff.`));
|
|
135559
135760
|
}
|
|
135560
135761
|
|
|
@@ -136173,7 +136374,7 @@ async function updatePhoneNumberVersions(publishedAgentIds, agentNames) {
|
|
|
136173
136374
|
// src/cli.ts
|
|
136174
136375
|
var program2 = new Command;
|
|
136175
136376
|
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);
|
|
136176
|
-
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);
|
|
136377
|
+
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").option("--no-tests", "Skip pulling test case definitions").action(pullCommand);
|
|
136177
136378
|
program2.command("deploy [agentIds...]").description("Deploy local changes to Retell draft").option("-a, --all", "Deploy all agents in the account").option("-s, --select", "Force interactive agent selection").option("-n, --dry-run", "Show changes without applying").option("-v, --verbose", "Show full diff details (use with --dry-run)").option("-q, --quiet", "Output only affected agent IDs (for piping)").action(deployCommand);
|
|
136178
136379
|
program2.command("publish [agentIds...]").description("Publish agents with unpublished draft changes").option("-a, --all", "Publish all agents in the account").option("-s, --select", "Force interactive agent selection").option("-n, --dry-run", "Show what would be published without publishing").option("-q, --quiet", "Output only published agent IDs (for piping)").action(publishCommand);
|
|
136179
136380
|
program2.parse();
|
package/package.json
CHANGED
package/.env.local
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
RETELL_API_KEY="key_12a24954adfaf146f4a3cd6616a3"
|
package/.oxlintrc.json
DELETED
package/.prettierrc.json
DELETED