eqho-eval 0.5.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 (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +552 -0
  3. package/dist/cli/auth-store.d.ts +5 -0
  4. package/dist/cli/auth-store.d.ts.map +1 -0
  5. package/dist/cli/auth-store.js +39 -0
  6. package/dist/cli/auth-store.js.map +1 -0
  7. package/dist/cli/banner.d.ts +3 -0
  8. package/dist/cli/banner.d.ts.map +1 -0
  9. package/dist/cli/banner.js +38 -0
  10. package/dist/cli/banner.js.map +1 -0
  11. package/dist/cli/commands/action-eval.d.ts +3 -0
  12. package/dist/cli/commands/action-eval.d.ts.map +1 -0
  13. package/dist/cli/commands/action-eval.js +133 -0
  14. package/dist/cli/commands/action-eval.js.map +1 -0
  15. package/dist/cli/commands/auth.d.ts +3 -0
  16. package/dist/cli/commands/auth.d.ts.map +1 -0
  17. package/dist/cli/commands/auth.js +156 -0
  18. package/dist/cli/commands/auth.js.map +1 -0
  19. package/dist/cli/commands/cache.d.ts +3 -0
  20. package/dist/cli/commands/cache.d.ts.map +1 -0
  21. package/dist/cli/commands/cache.js +43 -0
  22. package/dist/cli/commands/cache.js.map +1 -0
  23. package/dist/cli/commands/ci.d.ts +3 -0
  24. package/dist/cli/commands/ci.d.ts.map +1 -0
  25. package/dist/cli/commands/ci.js +124 -0
  26. package/dist/cli/commands/ci.js.map +1 -0
  27. package/dist/cli/commands/conversations.d.ts +3 -0
  28. package/dist/cli/commands/conversations.d.ts.map +1 -0
  29. package/dist/cli/commands/conversations.js +89 -0
  30. package/dist/cli/commands/conversations.js.map +1 -0
  31. package/dist/cli/commands/diff.d.ts +3 -0
  32. package/dist/cli/commands/diff.d.ts.map +1 -0
  33. package/dist/cli/commands/diff.js +122 -0
  34. package/dist/cli/commands/diff.js.map +1 -0
  35. package/dist/cli/commands/doctor.d.ts +11 -0
  36. package/dist/cli/commands/doctor.d.ts.map +1 -0
  37. package/dist/cli/commands/doctor.js +308 -0
  38. package/dist/cli/commands/doctor.js.map +1 -0
  39. package/dist/cli/commands/eval.d.ts +3 -0
  40. package/dist/cli/commands/eval.d.ts.map +1 -0
  41. package/dist/cli/commands/eval.js +101 -0
  42. package/dist/cli/commands/eval.js.map +1 -0
  43. package/dist/cli/commands/init.d.ts +3 -0
  44. package/dist/cli/commands/init.d.ts.map +1 -0
  45. package/dist/cli/commands/init.js +182 -0
  46. package/dist/cli/commands/init.js.map +1 -0
  47. package/dist/cli/commands/list.d.ts +3 -0
  48. package/dist/cli/commands/list.d.ts.map +1 -0
  49. package/dist/cli/commands/list.js +80 -0
  50. package/dist/cli/commands/list.js.map +1 -0
  51. package/dist/cli/commands/mentions.d.ts +3 -0
  52. package/dist/cli/commands/mentions.d.ts.map +1 -0
  53. package/dist/cli/commands/mentions.js +125 -0
  54. package/dist/cli/commands/mentions.js.map +1 -0
  55. package/dist/cli/commands/org.d.ts +3 -0
  56. package/dist/cli/commands/org.d.ts.map +1 -0
  57. package/dist/cli/commands/org.js +196 -0
  58. package/dist/cli/commands/org.js.map +1 -0
  59. package/dist/cli/commands/postcall-eval.d.ts +3 -0
  60. package/dist/cli/commands/postcall-eval.d.ts.map +1 -0
  61. package/dist/cli/commands/postcall-eval.js +188 -0
  62. package/dist/cli/commands/postcall-eval.js.map +1 -0
  63. package/dist/cli/commands/render.d.ts +3 -0
  64. package/dist/cli/commands/render.d.ts.map +1 -0
  65. package/dist/cli/commands/render.js +223 -0
  66. package/dist/cli/commands/render.js.map +1 -0
  67. package/dist/cli/commands/results.d.ts +3 -0
  68. package/dist/cli/commands/results.d.ts.map +1 -0
  69. package/dist/cli/commands/results.js +128 -0
  70. package/dist/cli/commands/results.js.map +1 -0
  71. package/dist/cli/commands/scenarios.d.ts +3 -0
  72. package/dist/cli/commands/scenarios.d.ts.map +1 -0
  73. package/dist/cli/commands/scenarios.js +57 -0
  74. package/dist/cli/commands/scenarios.js.map +1 -0
  75. package/dist/cli/commands/start.d.ts +3 -0
  76. package/dist/cli/commands/start.d.ts.map +1 -0
  77. package/dist/cli/commands/start.js +260 -0
  78. package/dist/cli/commands/start.js.map +1 -0
  79. package/dist/cli/commands/status.d.ts +3 -0
  80. package/dist/cli/commands/status.d.ts.map +1 -0
  81. package/dist/cli/commands/status.js +133 -0
  82. package/dist/cli/commands/status.js.map +1 -0
  83. package/dist/cli/commands/sync.d.ts +3 -0
  84. package/dist/cli/commands/sync.d.ts.map +1 -0
  85. package/dist/cli/commands/sync.js +80 -0
  86. package/dist/cli/commands/sync.js.map +1 -0
  87. package/dist/cli/commands/view.d.ts +3 -0
  88. package/dist/cli/commands/view.d.ts.map +1 -0
  89. package/dist/cli/commands/view.js +29 -0
  90. package/dist/cli/commands/view.js.map +1 -0
  91. package/dist/cli/error-handler.d.ts +8 -0
  92. package/dist/cli/error-handler.d.ts.map +1 -0
  93. package/dist/cli/error-handler.js +133 -0
  94. package/dist/cli/error-handler.js.map +1 -0
  95. package/dist/cli/gateway.d.ts +14 -0
  96. package/dist/cli/gateway.d.ts.map +1 -0
  97. package/dist/cli/gateway.js +222 -0
  98. package/dist/cli/gateway.js.map +1 -0
  99. package/dist/cli/index.d.ts +3 -0
  100. package/dist/cli/index.d.ts.map +1 -0
  101. package/dist/cli/index.js +194 -0
  102. package/dist/cli/index.js.map +1 -0
  103. package/dist/core/action-eval-builder.d.ts +20 -0
  104. package/dist/core/action-eval-builder.d.ts.map +1 -0
  105. package/dist/core/action-eval-builder.js +276 -0
  106. package/dist/core/action-eval-builder.js.map +1 -0
  107. package/dist/core/agent-fetcher.d.ts +35 -0
  108. package/dist/core/agent-fetcher.d.ts.map +1 -0
  109. package/dist/core/agent-fetcher.js +81 -0
  110. package/dist/core/agent-fetcher.js.map +1 -0
  111. package/dist/core/api-cache.d.ts +11 -0
  112. package/dist/core/api-cache.d.ts.map +1 -0
  113. package/dist/core/api-cache.js +89 -0
  114. package/dist/core/api-cache.js.map +1 -0
  115. package/dist/core/config-generator.d.ts +26 -0
  116. package/dist/core/config-generator.d.ts.map +1 -0
  117. package/dist/core/config-generator.js +457 -0
  118. package/dist/core/config-generator.js.map +1 -0
  119. package/dist/core/conversation-loader.d.ts +21 -0
  120. package/dist/core/conversation-loader.d.ts.map +1 -0
  121. package/dist/core/conversation-loader.js +74 -0
  122. package/dist/core/conversation-loader.js.map +1 -0
  123. package/dist/core/dataset-loader.d.ts +26 -0
  124. package/dist/core/dataset-loader.d.ts.map +1 -0
  125. package/dist/core/dataset-loader.js +121 -0
  126. package/dist/core/dataset-loader.js.map +1 -0
  127. package/dist/core/disposition-builder.d.ts +38 -0
  128. package/dist/core/disposition-builder.d.ts.map +1 -0
  129. package/dist/core/disposition-builder.js +270 -0
  130. package/dist/core/disposition-builder.js.map +1 -0
  131. package/dist/core/eqho-client.d.ts +45 -0
  132. package/dist/core/eqho-client.d.ts.map +1 -0
  133. package/dist/core/eqho-client.js +154 -0
  134. package/dist/core/eqho-client.js.map +1 -0
  135. package/dist/core/greeting-builder.d.ts +18 -0
  136. package/dist/core/greeting-builder.d.ts.map +1 -0
  137. package/dist/core/greeting-builder.js +83 -0
  138. package/dist/core/greeting-builder.js.map +1 -0
  139. package/dist/core/postcall-simulator.d.ts +20 -0
  140. package/dist/core/postcall-simulator.d.ts.map +1 -0
  141. package/dist/core/postcall-simulator.js +212 -0
  142. package/dist/core/postcall-simulator.js.map +1 -0
  143. package/dist/core/prompt-assembler.d.ts +25 -0
  144. package/dist/core/prompt-assembler.d.ts.map +1 -0
  145. package/dist/core/prompt-assembler.js +185 -0
  146. package/dist/core/prompt-assembler.js.map +1 -0
  147. package/dist/core/promptfoo-runner.d.ts +13 -0
  148. package/dist/core/promptfoo-runner.d.ts.map +1 -0
  149. package/dist/core/promptfoo-runner.js +49 -0
  150. package/dist/core/promptfoo-runner.js.map +1 -0
  151. package/dist/core/provider-mapper.d.ts +39 -0
  152. package/dist/core/provider-mapper.d.ts.map +1 -0
  153. package/dist/core/provider-mapper.js +120 -0
  154. package/dist/core/provider-mapper.js.map +1 -0
  155. package/dist/core/template-engine.d.ts +10 -0
  156. package/dist/core/template-engine.d.ts.map +1 -0
  157. package/dist/core/template-engine.js +78 -0
  158. package/dist/core/template-engine.js.map +1 -0
  159. package/dist/core/tools-builder.d.ts +14 -0
  160. package/dist/core/tools-builder.d.ts.map +1 -0
  161. package/dist/core/tools-builder.js +208 -0
  162. package/dist/core/tools-builder.js.map +1 -0
  163. package/dist/index.d.ts +18 -0
  164. package/dist/index.d.ts.map +1 -0
  165. package/dist/index.js +16 -0
  166. package/dist/index.js.map +1 -0
  167. package/dist/types/config.d.ts +100 -0
  168. package/dist/types/config.d.ts.map +1 -0
  169. package/dist/types/config.js +2 -0
  170. package/dist/types/config.js.map +1 -0
  171. package/dist/types/eqho.d.ts +221 -0
  172. package/dist/types/eqho.d.ts.map +1 -0
  173. package/dist/types/eqho.js +2 -0
  174. package/dist/types/eqho.js.map +1 -0
  175. package/dist/types/helpers.d.ts +9 -0
  176. package/dist/types/helpers.d.ts.map +1 -0
  177. package/dist/types/helpers.js +8 -0
  178. package/dist/types/helpers.js.map +1 -0
  179. package/package.json +77 -0
@@ -0,0 +1,133 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { EqhoClient, EqhoApiError } from "../../core/eqho-client.js";
7
+ import { fetchCampaignAgents, resolveSystemPromptSections, } from "../../core/agent-fetcher.js";
8
+ import { assemblePrompt } from "../../core/prompt-assembler.js";
9
+ import { generateActionEvalConfig } from "../../core/action-eval-builder.js";
10
+ import { loadAuth } from "../auth-store.js";
11
+ import { getProxyConfig } from "../../core/provider-mapper.js";
12
+ import { getId } from "../../types/helpers.js";
13
+ export const actionEvalCommand = new Command("action-eval")
14
+ .description("Generate eval config for testing live (in-call) action/tool usage")
15
+ .option("-c, --campaign <id>", "Campaign ID (reads from eqho.config.json if omitted)")
16
+ .option("-a, --agent <id>", "Specific agent ID (default: first agent in campaign)")
17
+ .option("-n, --calls <count>", "Number of real calls to use as ground truth", "0")
18
+ .option("-o, --output <dir>", "Output directory", ".")
19
+ .option("-d, --dir <dir>", "Project directory (for reading eqho.config.json)", ".")
20
+ .action(async (opts) => {
21
+ const auth = loadAuth();
22
+ if (!auth) {
23
+ console.log(chalk.red("Not authenticated. Run: eqho-eval auth"));
24
+ process.exit(1);
25
+ }
26
+ const client = new EqhoClient(auth);
27
+ let campaignId = opts.campaign;
28
+ if (!campaignId) {
29
+ const configPath = path.resolve(opts.dir, "eqho.config.json");
30
+ if (fs.existsSync(configPath)) {
31
+ try {
32
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
33
+ campaignId = config.campaignId;
34
+ }
35
+ catch {
36
+ // ignore
37
+ }
38
+ }
39
+ }
40
+ if (!campaignId) {
41
+ console.log(chalk.red("No campaign ID. Use --campaign <id> or run from an init'd project."));
42
+ process.exit(1);
43
+ }
44
+ const spinner = ora({ text: "Fetching campaign and agent data...", stream: process.stderr }).start();
45
+ let campaign;
46
+ try {
47
+ campaign = await client.getCampaign(campaignId);
48
+ }
49
+ catch (err) {
50
+ spinner.fail(`Failed to fetch campaign: ${err instanceof EqhoApiError ? err.message : String(err)}`);
51
+ process.exit(1);
52
+ }
53
+ const { agents, errors } = await fetchCampaignAgents(client, campaign, {
54
+ agentId: opts.agent,
55
+ onProgress: (msg) => {
56
+ spinner.text = msg;
57
+ },
58
+ });
59
+ if (errors.length) {
60
+ for (const e of errors)
61
+ console.log(chalk.yellow(` Warning: ${e}`));
62
+ }
63
+ if (!agents.length) {
64
+ spinner.fail("No agents loaded from campaign.");
65
+ process.exit(1);
66
+ }
67
+ const agentData = agents[0];
68
+ const { agent } = agentData;
69
+ const { sections, seeder } = resolveSystemPromptSections(agent, campaign);
70
+ spinner.text = `Assembling prompt for ${agent.name}...`;
71
+ const assembled = assemblePrompt({
72
+ agent,
73
+ campaign,
74
+ roles: agent.roles,
75
+ actions: agent.actions,
76
+ scripts: agent.scripts,
77
+ systemPromptSections: sections,
78
+ conversationSeeder: seeder,
79
+ });
80
+ let calls;
81
+ const callCount = parseInt(opts.calls, 10);
82
+ if (callCount > 0) {
83
+ spinner.text = `Fetching ${callCount} real calls...`;
84
+ try {
85
+ const { calls: rawCalls } = await client.listCalls(campaignId, {
86
+ limit: callCount,
87
+ });
88
+ const fullCalls = [];
89
+ for (const call of rawCalls) {
90
+ spinner.text = `Fetching transcript ${fullCalls.length + 1}/${rawCalls.length}...`;
91
+ try {
92
+ const full = await client.getCall(getId(call));
93
+ if (full.transcript?.length)
94
+ fullCalls.push(full);
95
+ }
96
+ catch {
97
+ // skip
98
+ }
99
+ }
100
+ calls = fullCalls;
101
+ spinner.text = `Loaded ${fullCalls.length} calls with transcripts`;
102
+ }
103
+ catch (err) {
104
+ console.log(chalk.yellow(` Warning: Failed to fetch calls: ${err instanceof EqhoApiError ? err.message : String(err)}`));
105
+ }
106
+ }
107
+ spinner.text = "Generating action eval config...";
108
+ const evalDir = path.join(path.resolve(opts.output), "action-eval");
109
+ const files = generateActionEvalConfig({
110
+ assembled,
111
+ actions: agent.actions,
112
+ campaignName: campaign.name,
113
+ calls,
114
+ proxy: getProxyConfig(loadAuth()),
115
+ });
116
+ let filesWritten = 0;
117
+ for (const [filePath, content] of Object.entries(files)) {
118
+ const fullPath = path.join(evalDir, filePath);
119
+ const dir = path.dirname(fullPath);
120
+ if (!fs.existsSync(dir))
121
+ fs.mkdirSync(dir, { recursive: true });
122
+ fs.writeFileSync(fullPath, content, "utf-8");
123
+ filesWritten++;
124
+ }
125
+ const liveCount = agent.actions.filter((a) => !a.execution_type || a.execution_type === "live").length;
126
+ spinner.succeed(`Generated ${filesWritten} files for ${campaign.name} (${liveCount} live actions)`);
127
+ console.log(chalk.dim(` Action eval → ${evalDir}/`));
128
+ console.log();
129
+ console.log(chalk.bold("Next steps:"));
130
+ console.log(chalk.dim(" cd action-eval && npx promptfoo eval"));
131
+ console.log(chalk.dim(" npx promptfoo view"));
132
+ });
133
+ //# sourceMappingURL=action-eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-eval.js","sourceRoot":"","sources":["../../../src/cli/commands/action-eval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const authCommand: Command;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,WAAW,SA+EpB,CAAC"}
@@ -0,0 +1,156 @@
1
+ import { Command } from "commander";
2
+ import { input } from "@inquirer/prompts";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import axios from "axios";
6
+ import { EqhoClient } from "../../core/eqho-client.js";
7
+ import { saveAuth, loadAuth, clearAuth } from "../auth-store.js";
8
+ const DEFAULT_BACKEND = "https://evals.eqho-solutions.dev";
9
+ export const authCommand = new Command("auth")
10
+ .description("Configure Eqho API authentication")
11
+ .option("--key <apiKey>", "Eqho API key (or enter interactively)")
12
+ .option("--login", "Sign in via browser (SSO) — enables org switching")
13
+ .option("--url <baseUrl>", "Eqho API base URL", "https://api.eqho.ai")
14
+ .option("--backend <url>", "eqho-eval backend URL", DEFAULT_BACKEND)
15
+ .option("--logout", "Remove stored credentials")
16
+ .action(async (opts) => {
17
+ if (opts.logout) {
18
+ clearAuth();
19
+ console.log(chalk.green("Credentials removed."));
20
+ return;
21
+ }
22
+ // ── SSO browser login flow ────────────────────────────────────────
23
+ if (opts.login) {
24
+ await handleLogin(opts.backend);
25
+ return;
26
+ }
27
+ // ── API key flow (existing) ───────────────────────────────────────
28
+ const existing = loadAuth();
29
+ if (existing && !opts.key) {
30
+ if (existing.authMode === "bearer") {
31
+ console.log(chalk.dim(`Current auth: SSO (${existing.email ?? "bearer"})`));
32
+ }
33
+ else {
34
+ console.log(chalk.dim(`Current API key: ${(existing.apiKey ?? "").slice(0, 8)}...`));
35
+ }
36
+ if (existing.backendToken) {
37
+ console.log(chalk.dim(`Backend: ${existing.backendUrl || DEFAULT_BACKEND}`));
38
+ }
39
+ }
40
+ const apiKey = opts.key ||
41
+ (await input({
42
+ message: "Eqho API key:",
43
+ validate: (v) => (v.trim().length > 0 ? true : "Required"),
44
+ }));
45
+ const spinner = ora({ text: "Validating connection...", stream: process.stderr }).start();
46
+ const client = new EqhoClient({
47
+ apiKey: apiKey.trim(),
48
+ baseUrl: opts.url,
49
+ });
50
+ const valid = await client.validateConnection();
51
+ if (!valid) {
52
+ spinner.fail("Could not connect to Eqho API. Check your API key.");
53
+ process.exit(1);
54
+ }
55
+ spinner.succeed("Authenticated with Eqho API");
56
+ let backendToken;
57
+ const backendUrl = opts.backend;
58
+ spinner.start("Registering with eqho-eval backend...");
59
+ try {
60
+ const res = await axios.post(`${backendUrl}/api/auth/token`, {
61
+ apiKey: apiKey.trim(),
62
+ apiUrl: opts.url,
63
+ }, { timeout: 10_000 });
64
+ backendToken = res.data.token;
65
+ spinner.succeed("Registered with backend (model proxy enabled)");
66
+ }
67
+ catch {
68
+ spinner.warn("Backend unavailable — direct mode (requires OPENAI_API_KEY)");
69
+ }
70
+ saveAuth({
71
+ authMode: "api_key",
72
+ apiKey: apiKey.trim(),
73
+ apiBaseUrl: opts.url,
74
+ backendUrl: backendToken ? backendUrl : undefined,
75
+ backendToken,
76
+ });
77
+ console.log(chalk.dim("Config saved to ~/.eqho-eval/config.json"));
78
+ });
79
+ async function handleLogin(backendUrl) {
80
+ const spinner = ora({ text: "Initiating browser login...", stream: process.stderr }).start();
81
+ let deviceCode;
82
+ let verificationUrl;
83
+ try {
84
+ const res = await axios.post(`${backendUrl}/api/auth/device`, {
85
+ backendUrl,
86
+ }, { timeout: 10_000 });
87
+ deviceCode = res.data.device_code;
88
+ verificationUrl = res.data.verification_url;
89
+ }
90
+ catch (err) {
91
+ spinner.fail("Could not reach eqho-eval backend.");
92
+ const msg = err instanceof Error ? err.message : "";
93
+ if (msg)
94
+ console.log(chalk.dim(` ${msg}`));
95
+ process.exit(1);
96
+ }
97
+ spinner.succeed("Opening browser to authenticate with Eqho...");
98
+ console.log();
99
+ console.log(chalk.dim(" If the browser doesn't open, visit:"));
100
+ console.log(chalk.cyan(` ${verificationUrl}`));
101
+ console.log();
102
+ // Open the browser
103
+ try {
104
+ const { exec } = await import("node:child_process");
105
+ const platform = process.platform;
106
+ const cmd = platform === "darwin" ? "open" :
107
+ platform === "win32" ? "start" :
108
+ "xdg-open";
109
+ exec(`${cmd} "${verificationUrl}"`);
110
+ }
111
+ catch { /* non-critical */ }
112
+ // Poll for completion
113
+ const pollSpinner = ora({ text: "Waiting for authentication...", stream: process.stderr }).start();
114
+ const maxAttempts = 150; // 10 min at 4s intervals
115
+ const pollInterval = 4_000;
116
+ for (let i = 0; i < maxAttempts; i++) {
117
+ await new Promise((r) => setTimeout(r, pollInterval));
118
+ try {
119
+ const res = await axios.post(`${backendUrl}/api/auth/device/poll`, {
120
+ device_code: deviceCode,
121
+ }, { timeout: 10_000 });
122
+ if (res.data.status === "completed") {
123
+ pollSpinner.succeed("Authenticated with Eqho");
124
+ const email = res.data.email;
125
+ const orgId = res.data.orgId;
126
+ if (email) {
127
+ console.log(chalk.green(` Signed in as ${email}`));
128
+ }
129
+ saveAuth({
130
+ authMode: "bearer",
131
+ apiBaseUrl: "https://api.eqho.ai",
132
+ email,
133
+ orgId,
134
+ backendUrl,
135
+ backendToken: res.data.token,
136
+ });
137
+ console.log(chalk.dim(" Config saved to ~/.eqho-eval/config.json"));
138
+ return;
139
+ }
140
+ if (res.data.status === "expired") {
141
+ pollSpinner.fail("Login session expired. Please try again.");
142
+ process.exit(1);
143
+ }
144
+ }
145
+ catch (err) {
146
+ const axErr = err;
147
+ if (axErr.response?.status === 400) {
148
+ pollSpinner.fail("Login session expired. Please try again.");
149
+ process.exit(1);
150
+ }
151
+ }
152
+ }
153
+ pollSpinner.fail("Login timed out. Please try again.");
154
+ process.exit(1);
155
+ }
156
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjE,MAAM,eAAe,GAAG,kCAAkC,CAAC;AAE3D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,gBAAgB,EAAE,uCAAuC,CAAC;KACjE,MAAM,CAAC,SAAS,EAAE,mDAAmD,CAAC;KACtE,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,qBAAqB,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,EAAE,eAAe,CAAC;KACnE,MAAM,CAAC,UAAU,EAAE,2BAA2B,CAAC;KAC/C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,qEAAqE;IACrE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,qEAAqE;IACrE,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC;IAC5B,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,QAAQ,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,UAAU,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GACV,IAAI,CAAC,GAAG;QACR,CAAC,MAAM,KAAK,CAAC;YACX,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;SAC3D,CAAC,CAAC,CAAC;IAEN,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAE1F,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;QACrB,OAAO,EAAE,IAAI,CAAC,GAAG;KAClB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;IAChD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAE/C,IAAI,YAAgC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,iBAAiB,EAAE;YAC3D,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,MAAM,EAAE,IAAI,CAAC,GAAG;SACjB,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxB,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,OAAO,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;IAC9E,CAAC;IAED,QAAQ,CAAC;QACP,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;QACrB,UAAU,EAAE,IAAI,CAAC,GAAG;QACpB,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QACjD,YAAY;KACb,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEL,KAAK,UAAU,WAAW,CAAC,UAAkB;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,6BAA6B,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAE7F,IAAI,UAAkB,CAAC;IACvB,IAAI,eAAuB,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,kBAAkB,EAAE;YAC5D,UAAU;SACX,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAExB,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;QAClC,eAAe,GAAG,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,IAAI,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,eAAe,EAAE,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,mBAAmB;IACnB,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,MAAM,GAAG,GACP,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAChC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBAChC,UAAU,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,KAAK,eAAe,GAAG,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAE9B,sBAAsB;IACtB,MAAM,WAAW,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IACnG,MAAM,WAAW,GAAG,GAAG,CAAC,CAAC,yBAAyB;IAClD,MAAM,YAAY,GAAG,KAAK,CAAC;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,uBAAuB,EAAE;gBACjE,WAAW,EAAE,UAAU;aACxB,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAExB,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACpC,WAAW,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;gBAE/C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAA2B,CAAC;gBACnD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAA2B,CAAC;gBAEnD,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC;gBACtD,CAAC;gBAED,QAAQ,CAAC;oBACP,QAAQ,EAAE,QAAQ;oBAClB,UAAU,EAAE,qBAAqB;oBACjC,KAAK;oBACL,KAAK;oBACL,UAAU;oBACV,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;iBAC7B,CAAC,CAAC;gBAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC,CAAC;gBACrE,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAClC,WAAW,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;gBAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,GAAwC,CAAC;YACvD,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,WAAW,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;gBAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const cacheCommand: Command;
3
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,YAAY,SAqCrB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { clearCache, cacheStats } from "../../core/api-cache.js";
4
+ export const cacheCommand = new Command("cache")
5
+ .description("Manage API response cache")
6
+ .argument("<action>", "Action: clear, stats")
7
+ .action(async (action, _opts, cmd) => {
8
+ const jsonMode = cmd.parent?.opts().json;
9
+ switch (action) {
10
+ case "clear": {
11
+ const { cleared } = clearCache();
12
+ if (jsonMode) {
13
+ console.log(JSON.stringify({ cleared }));
14
+ }
15
+ else {
16
+ console.log(chalk.green(` ✓ Cleared ${cleared} cached entries`));
17
+ }
18
+ break;
19
+ }
20
+ case "stats": {
21
+ const stats = cacheStats();
22
+ if (jsonMode) {
23
+ console.log(JSON.stringify(stats, null, 2));
24
+ }
25
+ else {
26
+ console.log();
27
+ console.log(chalk.bold(" Cache stats:"));
28
+ console.log(chalk.dim(` Entries: ${stats.entries}`));
29
+ console.log(chalk.dim(` Size: ${(stats.sizeBytes / 1024).toFixed(1)} KB`));
30
+ if (stats.oldestMs !== null) {
31
+ const mins = Math.floor(stats.oldestMs / 60_000);
32
+ console.log(chalk.dim(` Oldest: ${mins}m ago`));
33
+ }
34
+ console.log();
35
+ }
36
+ break;
37
+ }
38
+ default:
39
+ console.log(chalk.red(`Unknown action: ${action}. Use: clear, stats`));
40
+ process.exit(1);
41
+ }
42
+ });
43
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/cli/commands/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,2BAA2B,CAAC;KACxC,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC3C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC;IAEzC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;YACjC,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,OAAO,iBAAiB,CAAC,CAAC,CAAC;YACpE,CAAC;YACD,MAAM;QACR,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;YAC3B,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjF,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;oBACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,CAAC,CAAC;gBACtD,CAAC;gBACD,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,CAAC;YACD,MAAM;QACR,CAAC;QACD;YACE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,MAAM,qBAAqB,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const ciCommand: Command;
3
+ //# sourceMappingURL=ci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoGpC,eAAO,MAAM,SAAS,SAmClB,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ const WORKFLOW_TEMPLATE = `name: Eqho Agent Eval
6
+
7
+ on:
8
+ pull_request:
9
+ paths:
10
+ - 'prompts/**'
11
+ - 'tools/**'
12
+ - 'promptfooconfig.yaml'
13
+ - 'tests/**'
14
+ workflow_dispatch:
15
+ inputs:
16
+ campaign_id:
17
+ description: 'Eqho Campaign ID'
18
+ required: false
19
+ threshold:
20
+ description: 'Minimum pass rate (0-100)'
21
+ required: false
22
+ default: '80'
23
+
24
+ permissions:
25
+ contents: read
26
+ pull-requests: write
27
+
28
+ jobs:
29
+ eval:
30
+ runs-on: ubuntu-latest
31
+ timeout-minutes: 15
32
+
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - uses: actions/setup-node@v4
37
+ with:
38
+ node-version: '20'
39
+ cache: 'npm'
40
+
41
+ - name: Install dependencies
42
+ run: npm ci
43
+
44
+ - name: Run promptfoo eval
45
+ env:
46
+ OPENAI_API_KEY: \${{ secrets.OPENAI_API_KEY }}
47
+ EQHO_API_KEY: \${{ secrets.EQHO_API_KEY }}
48
+ run: npx promptfoo eval --no-cache -o output/eval-results.json
49
+
50
+ - name: Check pass rate
51
+ run: |
52
+ THRESHOLD=\${{ github.event.inputs.threshold || '80' }}
53
+ RESULT=$(node -e "
54
+ const r = require('./output/eval-results.json');
55
+ const s = r.results?.stats || r.stats;
56
+ const total = s.successes + s.failures + (s.errors || 0);
57
+ const pct = total > 0 ? (s.successes / total * 100) : 0;
58
+ console.log(JSON.stringify({ pct: pct.toFixed(1), pass: s.successes, fail: s.failures, errors: s.errors || 0, total }));
59
+ process.exit(pct < $THRESHOLD ? 1 : 0);
60
+ ")
61
+ echo "::notice::Eval results: $RESULT"
62
+
63
+ - name: Comment PR with results
64
+ if: github.event_name == 'pull_request' && always()
65
+ uses: actions/github-script@v7
66
+ with:
67
+ script: |
68
+ const fs = require('fs');
69
+ let body = '## Eqho Agent Eval Results\\n\\n';
70
+ try {
71
+ const r = JSON.parse(fs.readFileSync('output/eval-results.json', 'utf8'));
72
+ const s = r.results?.stats || r.stats;
73
+ const total = s.successes + s.failures + (s.errors || 0);
74
+ const pct = total > 0 ? (s.successes / total * 100).toFixed(1) : '0';
75
+ const emoji = pct >= 80 ? '✅' : pct >= 60 ? '⚠️' : '❌';
76
+ body += \`\${emoji} **\${pct}%** pass rate (\${s.successes}/\${total})\\n\\n\`;
77
+ body += \`| Metric | Count |\\n|--------|-------|\\n\`;
78
+ body += \`| Passed | \${s.successes} |\\n\`;
79
+ body += \`| Failed | \${s.failures} |\\n\`;
80
+ body += \`| Errors | \${s.errors || 0} |\\n\`;
81
+ } catch (e) {
82
+ body += '❌ Failed to parse eval results.\\n';
83
+ }
84
+ github.rest.issues.createComment({
85
+ issue_number: context.issue.number,
86
+ owner: context.repo.owner,
87
+ repo: context.repo.repo,
88
+ body
89
+ });
90
+
91
+ - name: Upload results artifact
92
+ if: always()
93
+ uses: actions/upload-artifact@v4
94
+ with:
95
+ name: eval-results
96
+ path: output/
97
+ retention-days: 30
98
+ `;
99
+ export const ciCommand = new Command("ci")
100
+ .description("Generate a GitHub Actions workflow for automated eval on PR")
101
+ .option("-o, --output <dir>", "Output directory", ".")
102
+ .option("--threshold <pct>", "Default pass rate threshold", "80")
103
+ .action(async (opts) => {
104
+ const outDir = path.resolve(opts.output);
105
+ const workflowDir = path.join(outDir, ".github", "workflows");
106
+ if (!fs.existsSync(workflowDir)) {
107
+ fs.mkdirSync(workflowDir, { recursive: true });
108
+ }
109
+ const workflowPath = path.join(workflowDir, "eqho-eval.yml");
110
+ const content = WORKFLOW_TEMPLATE.replace("default: '80'", `default: '${opts.threshold}'`);
111
+ fs.writeFileSync(workflowPath, content, "utf-8");
112
+ console.log(chalk.green(`GitHub Actions workflow written to ${workflowPath}`));
113
+ console.log();
114
+ console.log(chalk.bold("Required secrets:"));
115
+ console.log(chalk.dim(" OPENAI_API_KEY — OpenAI API key for running evals"));
116
+ console.log(chalk.dim(" EQHO_API_KEY — Eqho API key (only for sync commands)"));
117
+ console.log();
118
+ console.log(chalk.bold("Triggers:"));
119
+ console.log(chalk.dim(" - On PR when prompts/, tools/, or config files change"));
120
+ console.log(chalk.dim(" - Manual dispatch with optional campaign_id and threshold"));
121
+ console.log();
122
+ console.log(chalk.dim(` Pass rate threshold: ${opts.threshold}% (PRs below this will show a warning)`));
123
+ });
124
+ //# sourceMappingURL=ci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../../../src/cli/commands/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FzB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;KACvC,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,GAAG,CAAC;KACrD,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,EAAE,IAAI,CAAC;KAChE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAE9D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CACvC,eAAe,EACf,aAAa,IAAI,CAAC,SAAS,GAAG,CAC/B,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sCAAsC,YAAY,EAAE,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,0BAA0B,IAAI,CAAC,SAAS,wCAAwC,CACjF,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const conversationsCommand: Command;
3
+ //# sourceMappingURL=conversations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,eAAO,MAAM,oBAAoB,SAiG7B,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { EqhoClient } from "../../core/eqho-client.js";
7
+ import { generateConversationTestsYaml } from "../../core/conversation-loader.js";
8
+ import { loadAuth } from "../auth-store.js";
9
+ import { getId } from "../../types/helpers.js";
10
+ export const conversationsCommand = new Command("conversations")
11
+ .description("Pull real conversations from Eqho as test cases")
12
+ .option("-c, --campaign <id>", "Campaign ID (reads from eqho.config.json if omitted)")
13
+ .option("-n, --last <count>", "Number of recent calls to pull", "25")
14
+ .option("-s, --status <filter>", "Filter by call status")
15
+ .option("-o, --output <file>", "Output file", "tests/conversations.yaml")
16
+ .option("-d, --dir <dir>", "Project directory", ".")
17
+ .action(async (opts, cmd) => {
18
+ const jsonMode = cmd.parent?.opts().json;
19
+ const auth = loadAuth();
20
+ if (!auth) {
21
+ if (jsonMode) {
22
+ console.log(JSON.stringify({ error: "Not authenticated", fix: "eqho-eval auth --key <key>" }));
23
+ }
24
+ else {
25
+ console.log(chalk.red("Not authenticated. Run: eqho-eval auth"));
26
+ }
27
+ process.exit(1);
28
+ }
29
+ let campaignId = opts.campaign;
30
+ if (!campaignId) {
31
+ const configPath = path.resolve(opts.dir, "eqho.config.json");
32
+ if (fs.existsSync(configPath)) {
33
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
34
+ campaignId = config.campaignId;
35
+ }
36
+ }
37
+ if (!campaignId) {
38
+ console.log(chalk.red("No campaign ID. Use --campaign <id> or run from an init'd project."));
39
+ process.exit(1);
40
+ }
41
+ const client = new EqhoClient(auth);
42
+ const spinner = ora({
43
+ text: `Pulling last ${opts.last} calls from campaign...`,
44
+ stream: process.stderr,
45
+ }).start();
46
+ const { calls } = await client.listCalls(campaignId, {
47
+ limit: parseInt(opts.last, 10),
48
+ status: opts.status,
49
+ });
50
+ if (!calls.length) {
51
+ spinner.warn("No calls found for this campaign.");
52
+ return;
53
+ }
54
+ // Fetch full transcripts for each call
55
+ const fullCalls = [];
56
+ for (const call of calls) {
57
+ spinner.text = `Fetching transcript ${fullCalls.length + 1}/${calls.length}...`;
58
+ try {
59
+ const full = await client.getCall(getId(call));
60
+ if (full.transcript?.length)
61
+ fullCalls.push(full);
62
+ }
63
+ catch {
64
+ // skip calls that fail to fetch
65
+ }
66
+ }
67
+ spinner.text = "Generating test cases...";
68
+ const yamlContent = generateConversationTestsYaml(fullCalls);
69
+ const outPath = path.resolve(opts.dir, opts.output);
70
+ const outDir = path.dirname(outPath);
71
+ if (!fs.existsSync(outDir))
72
+ fs.mkdirSync(outDir, { recursive: true });
73
+ fs.writeFileSync(outPath, yamlContent, "utf-8");
74
+ const lineCount = yamlContent.split("\n").length;
75
+ spinner.succeed(`Generated ${lineCount} lines of test cases from ${fullCalls.length} calls → ${opts.output}`);
76
+ if (jsonMode) {
77
+ console.log(JSON.stringify({
78
+ outputFile: outPath,
79
+ callsProcessed: fullCalls.length,
80
+ linesGenerated: lineCount,
81
+ }));
82
+ }
83
+ else {
84
+ console.log();
85
+ console.log(chalk.bold("To use in your eval:"));
86
+ console.log(chalk.dim(" Add to promptfooconfig.yaml:\n tests: file://tests/conversations.yaml"));
87
+ }
88
+ });
89
+ //# sourceMappingURL=conversations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../../src/cli/commands/conversations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const diffCommand: Command;
3
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,eAAO,MAAM,WAAW,SA2IpB,CAAC"}