@wix/evalforge-evaluator 0.97.0 → 0.99.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/build/index.js CHANGED
@@ -207,6 +207,53 @@ function createApiClient(serverUrl, options = "") {
207
207
 
208
208
  // src/fetch-evaluation-data.ts
209
209
  var import_evalforge_types = require("@wix/evalforge-types");
210
+
211
+ // src/resolve-placeholders.ts
212
+ var PLACEHOLDER_PATTERN = /\{\{([^}]+)\}\}/g;
213
+ function findPlaceholders(value) {
214
+ const keys = /* @__PURE__ */ new Set();
215
+ collectPlaceholders(value, keys);
216
+ return [...keys];
217
+ }
218
+ function collectPlaceholders(value, keys) {
219
+ if (typeof value === "string") {
220
+ for (const match of value.matchAll(PLACEHOLDER_PATTERN)) {
221
+ keys.add(match[1].trim());
222
+ }
223
+ } else if (Array.isArray(value)) {
224
+ for (const item of value) {
225
+ collectPlaceholders(item, keys);
226
+ }
227
+ } else if (typeof value === "object" && value !== null) {
228
+ for (const val of Object.values(value)) {
229
+ collectPlaceholders(val, keys);
230
+ }
231
+ }
232
+ }
233
+ function resolveValue(value, placeholders) {
234
+ if (typeof value === "string") {
235
+ return value.replace(PLACEHOLDER_PATTERN, (match, key) => {
236
+ const trimmed = key.trim();
237
+ return trimmed in placeholders ? placeholders[trimmed] : match;
238
+ });
239
+ }
240
+ if (Array.isArray(value)) {
241
+ return value.map((item) => resolveValue(item, placeholders));
242
+ }
243
+ if (typeof value === "object" && value !== null) {
244
+ const result = {};
245
+ for (const [k, v] of Object.entries(value)) {
246
+ result[k] = resolveValue(v, placeholders);
247
+ }
248
+ return result;
249
+ }
250
+ return value;
251
+ }
252
+ function resolvePlaceholdersInString(text, placeholders) {
253
+ return resolveValue(text, placeholders);
254
+ }
255
+
256
+ // src/fetch-evaluation-data.ts
210
257
  function parseSkillNamesFromParams(value) {
211
258
  if (typeof value !== "string") {
212
259
  return [];
@@ -222,13 +269,11 @@ function applyParamsToAssertion(assertion, params) {
222
269
  return assertion;
223
270
  }
224
271
  if (assertion.type === "llm_judge") {
225
- let prompt = assertion.prompt;
272
+ const stringParams = {};
226
273
  for (const [key, value] of Object.entries(params)) {
227
- const placeholder = `{{${key}}}`;
228
- const escapedPlaceholder = placeholder.replace(/[{}]/g, "\\$&");
229
- const replacement = String(value ?? "");
230
- prompt = prompt.replace(new RegExp(escapedPlaceholder, "g"), replacement);
274
+ stringParams[key] = String(value ?? "");
231
275
  }
276
+ const prompt = resolvePlaceholdersInString(assertion.prompt, stringParams);
232
277
  return {
233
278
  ...assertion,
234
279
  prompt,
@@ -697,9 +742,50 @@ var import_evalforge_types3 = require("@wix/evalforge-types");
697
742
  var import_crypto = require("crypto");
698
743
 
699
744
  // src/run-scenario/agents/claude-code/write-mcp.ts
745
+ var import_promises3 = require("fs/promises");
746
+ var import_path4 = require("path");
747
+ var import_evalforge_types2 = require("@wix/evalforge-types");
748
+
749
+ // src/run-scenario/agents/claude-code/resolve-mcp-placeholders.ts
700
750
  var import_promises2 = require("fs/promises");
701
751
  var import_path3 = require("path");
702
- var import_evalforge_types2 = require("@wix/evalforge-types");
752
+ var import_os2 = require("os");
753
+ var WIX_AUTH_FILE = (0, import_path3.join)((0, import_os2.homedir)(), ".wix", "auth", "api-key.json");
754
+ async function loadWixAuthPlaceholders(authFilePath = WIX_AUTH_FILE) {
755
+ try {
756
+ const content = await (0, import_promises2.readFile)(authFilePath, "utf-8");
757
+ const auth = JSON.parse(content);
758
+ if (!auth.token || !auth.userInfo?.userId) {
759
+ return {};
760
+ }
761
+ return {
762
+ "wix-auth-token": auth.token,
763
+ "wix-auth-user-id": auth.userInfo.userId
764
+ };
765
+ } catch (err) {
766
+ console.warn(
767
+ `[MCP] Could not load Wix auth file: ${err.message}`
768
+ );
769
+ return {};
770
+ }
771
+ }
772
+ async function resolveMcpPlaceholders(mcpServers, authFilePath) {
773
+ const needed = findPlaceholders(mcpServers);
774
+ if (needed.length === 0) {
775
+ return mcpServers;
776
+ }
777
+ const placeholders = await loadWixAuthPlaceholders(authFilePath);
778
+ const unresolved = needed.filter((key) => !(key in placeholders));
779
+ if (unresolved.length > 0) {
780
+ throw new Error(
781
+ `MCP config contains unresolvable placeholders: ${unresolved.map((k) => `{{${k}}}`).join(", ")}. Ensure ~/.wix/auth/api-key.json exists (run \`npx @wix/cli login\`).`
782
+ );
783
+ }
784
+ console.log(`[MCP] Resolved ${needed.length} placeholder(s)`);
785
+ return resolveValue(mcpServers, placeholders);
786
+ }
787
+
788
+ // src/run-scenario/agents/claude-code/write-mcp.ts
703
789
  async function writeMcpToFilesystem(cwd, mcps) {
704
790
  if (mcps.length === 0) return;
705
791
  const mcpServers = {};
@@ -714,19 +800,20 @@ async function writeMcpToFilesystem(cwd, mcps) {
714
800
  mcpServers[key] = value;
715
801
  }
716
802
  }
803
+ const resolvedServers = await resolveMcpPlaceholders(mcpServers);
717
804
  const content = JSON.stringify(
718
- { [import_evalforge_types2.MCP_SERVERS_JSON_KEY]: mcpServers },
805
+ { [import_evalforge_types2.MCP_SERVERS_JSON_KEY]: resolvedServers },
719
806
  null,
720
807
  2
721
808
  );
722
- const filePath = (0, import_path3.join)(cwd, ".mcp.json");
723
- await (0, import_promises2.writeFile)(filePath, content, "utf8");
809
+ const filePath = (0, import_path4.join)(cwd, ".mcp.json");
810
+ await (0, import_promises3.writeFile)(filePath, content, "utf8");
724
811
  console.log(`[MCP] Written to ${filePath}`);
725
812
  }
726
813
 
727
814
  // src/run-scenario/agents/claude-code/write-sub-agents.ts
728
- var import_promises3 = require("fs/promises");
729
- var import_path4 = require("path");
815
+ var import_promises4 = require("fs/promises");
816
+ var import_path5 = require("path");
730
817
  var AGENTS_DIR = ".claude/agents";
731
818
  function toAgentFilename(name, index, nameCount) {
732
819
  const base = (name || "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "") || `sub-agent-${index}`;
@@ -736,20 +823,20 @@ function toAgentFilename(name, index, nameCount) {
736
823
  }
737
824
  async function writeSubAgentsToFilesystem(cwd, subAgents) {
738
825
  if (subAgents.length === 0) return;
739
- const agentsDir = (0, import_path4.join)(cwd, AGENTS_DIR);
740
- await (0, import_promises3.mkdir)(agentsDir, { recursive: true });
826
+ const agentsDir = (0, import_path5.join)(cwd, AGENTS_DIR);
827
+ await (0, import_promises4.mkdir)(agentsDir, { recursive: true });
741
828
  const nameCount = /* @__PURE__ */ new Map();
742
829
  for (const [i, agent] of subAgents.entries()) {
743
830
  const filename = toAgentFilename(agent.name, i, nameCount);
744
- const filePath = (0, import_path4.join)(agentsDir, `${filename}.md`);
745
- await (0, import_promises3.writeFile)(filePath, agent.subAgentMd, "utf8");
831
+ const filePath = (0, import_path5.join)(agentsDir, `${filename}.md`);
832
+ await (0, import_promises4.writeFile)(filePath, agent.subAgentMd, "utf8");
746
833
  }
747
834
  console.log(`[SubAgents] Written to ${agentsDir}`);
748
835
  }
749
836
 
750
837
  // src/run-scenario/agents/claude-code/write-rules.ts
751
- var import_promises4 = require("fs/promises");
752
- var import_path5 = require("path");
838
+ var import_promises5 = require("fs/promises");
839
+ var import_path6 = require("path");
753
840
  var CURSOR_RULES_DIR = ".cursor/rules";
754
841
  function toRuleFilename(name, index, nameCount) {
755
842
  const base = (name || "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "") || `rule-${index}`;
@@ -760,13 +847,13 @@ function toRuleFilename(name, index, nameCount) {
760
847
  async function appendToFile(filePath, content) {
761
848
  let existing = "";
762
849
  try {
763
- existing = await (0, import_promises4.readFile)(filePath, "utf8");
850
+ existing = await (0, import_promises5.readFile)(filePath, "utf8");
764
851
  } catch {
765
852
  }
766
853
  const merged = existing ? `${existing.trimEnd()}
767
854
 
768
855
  ${content}` : content;
769
- await (0, import_promises4.writeFile)(filePath, merged, "utf8");
856
+ await (0, import_promises5.writeFile)(filePath, merged, "utf8");
770
857
  }
771
858
  async function writeRulesToFilesystem(cwd, rules) {
772
859
  if (rules.length === 0) return;
@@ -775,21 +862,21 @@ async function writeRulesToFilesystem(cwd, rules) {
775
862
  for (const [i, rule] of rules.entries()) {
776
863
  switch (rule.ruleType) {
777
864
  case "claude-md": {
778
- await appendToFile((0, import_path5.join)(cwd, "CLAUDE.md"), rule.content);
865
+ await appendToFile((0, import_path6.join)(cwd, "CLAUDE.md"), rule.content);
779
866
  break;
780
867
  }
781
868
  case "agents-md": {
782
- await appendToFile((0, import_path5.join)(cwd, "AGENTS.md"), rule.content);
869
+ await appendToFile((0, import_path6.join)(cwd, "AGENTS.md"), rule.content);
783
870
  break;
784
871
  }
785
872
  case "cursor-rule": {
786
873
  if (!hasCursorRules) {
787
- await (0, import_promises4.mkdir)((0, import_path5.join)(cwd, CURSOR_RULES_DIR), { recursive: true });
874
+ await (0, import_promises5.mkdir)((0, import_path6.join)(cwd, CURSOR_RULES_DIR), { recursive: true });
788
875
  hasCursorRules = true;
789
876
  }
790
877
  const filename = toRuleFilename(rule.name, i, nameCount);
791
- const filePath = (0, import_path5.join)(cwd, CURSOR_RULES_DIR, `${filename}.md`);
792
- await (0, import_promises4.writeFile)(filePath, rule.content, "utf8");
878
+ const filePath = (0, import_path6.join)(cwd, CURSOR_RULES_DIR, `${filename}.md`);
879
+ await (0, import_promises5.writeFile)(filePath, rule.content, "utf8");
793
880
  break;
794
881
  }
795
882
  }
@@ -1824,7 +1911,7 @@ defaultRegistry.register(claudeCodeAdapter);
1824
1911
 
1825
1912
  // src/run-scenario/file-diff.ts
1826
1913
  var import_fs2 = require("fs");
1827
- var import_path6 = require("path");
1914
+ var import_path7 = require("path");
1828
1915
 
1829
1916
  // ../../node_modules/diff/lib/index.mjs
1830
1917
  function Diff() {
@@ -2000,7 +2087,7 @@ Diff.prototype = {
2000
2087
  tokenize: function tokenize(value) {
2001
2088
  return Array.from(value);
2002
2089
  },
2003
- join: function join5(chars) {
2090
+ join: function join6(chars) {
2004
2091
  return chars.join("");
2005
2092
  },
2006
2093
  postProcess: function postProcess(changeObjects) {
@@ -2440,8 +2527,8 @@ function snapshotDirectory(dir, baseDir) {
2440
2527
  }
2441
2528
  const entries = (0, import_fs2.readdirSync)(dir, { withFileTypes: true });
2442
2529
  for (const entry of entries) {
2443
- const fullPath = (0, import_path6.join)(dir, entry.name);
2444
- const relativePath = (0, import_path6.relative)(base, fullPath);
2530
+ const fullPath = (0, import_path7.join)(dir, entry.name);
2531
+ const relativePath = (0, import_path7.relative)(base, fullPath);
2445
2532
  if (shouldIgnore(entry.name)) {
2446
2533
  continue;
2447
2534
  }