@wix/evalforge-evaluator 0.98.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 +115 -28
- package/build/index.js.map +4 -4
- package/build/index.mjs +108 -21
- package/build/index.mjs.map +4 -4
- package/build/types/resolve-placeholders.d.ts +26 -0
- package/build/types/run-scenario/agents/claude-code/resolve-mcp-placeholders.d.ts +31 -0
- package/build/types/run-scenario/agents/claude-code/write-mcp.d.ts +3 -0
- package/package.json +2 -2
package/build/index.mjs
CHANGED
|
@@ -187,6 +187,53 @@ import {
|
|
|
187
187
|
isSystemAssertionId,
|
|
188
188
|
SYSTEM_ASSERTIONS
|
|
189
189
|
} from "@wix/evalforge-types";
|
|
190
|
+
|
|
191
|
+
// src/resolve-placeholders.ts
|
|
192
|
+
var PLACEHOLDER_PATTERN = /\{\{([^}]+)\}\}/g;
|
|
193
|
+
function findPlaceholders(value) {
|
|
194
|
+
const keys = /* @__PURE__ */ new Set();
|
|
195
|
+
collectPlaceholders(value, keys);
|
|
196
|
+
return [...keys];
|
|
197
|
+
}
|
|
198
|
+
function collectPlaceholders(value, keys) {
|
|
199
|
+
if (typeof value === "string") {
|
|
200
|
+
for (const match of value.matchAll(PLACEHOLDER_PATTERN)) {
|
|
201
|
+
keys.add(match[1].trim());
|
|
202
|
+
}
|
|
203
|
+
} else if (Array.isArray(value)) {
|
|
204
|
+
for (const item of value) {
|
|
205
|
+
collectPlaceholders(item, keys);
|
|
206
|
+
}
|
|
207
|
+
} else if (typeof value === "object" && value !== null) {
|
|
208
|
+
for (const val of Object.values(value)) {
|
|
209
|
+
collectPlaceholders(val, keys);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function resolveValue(value, placeholders) {
|
|
214
|
+
if (typeof value === "string") {
|
|
215
|
+
return value.replace(PLACEHOLDER_PATTERN, (match, key) => {
|
|
216
|
+
const trimmed = key.trim();
|
|
217
|
+
return trimmed in placeholders ? placeholders[trimmed] : match;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (Array.isArray(value)) {
|
|
221
|
+
return value.map((item) => resolveValue(item, placeholders));
|
|
222
|
+
}
|
|
223
|
+
if (typeof value === "object" && value !== null) {
|
|
224
|
+
const result = {};
|
|
225
|
+
for (const [k, v] of Object.entries(value)) {
|
|
226
|
+
result[k] = resolveValue(v, placeholders);
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
function resolvePlaceholdersInString(text, placeholders) {
|
|
233
|
+
return resolveValue(text, placeholders);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/fetch-evaluation-data.ts
|
|
190
237
|
function parseSkillNamesFromParams(value) {
|
|
191
238
|
if (typeof value !== "string") {
|
|
192
239
|
return [];
|
|
@@ -202,13 +249,11 @@ function applyParamsToAssertion(assertion, params) {
|
|
|
202
249
|
return assertion;
|
|
203
250
|
}
|
|
204
251
|
if (assertion.type === "llm_judge") {
|
|
205
|
-
|
|
252
|
+
const stringParams = {};
|
|
206
253
|
for (const [key, value] of Object.entries(params)) {
|
|
207
|
-
|
|
208
|
-
const escapedPlaceholder = placeholder.replace(/[{}]/g, "\\$&");
|
|
209
|
-
const replacement = String(value ?? "");
|
|
210
|
-
prompt = prompt.replace(new RegExp(escapedPlaceholder, "g"), replacement);
|
|
254
|
+
stringParams[key] = String(value ?? "");
|
|
211
255
|
}
|
|
256
|
+
const prompt = resolvePlaceholdersInString(assertion.prompt, stringParams);
|
|
212
257
|
return {
|
|
213
258
|
...assertion,
|
|
214
259
|
prompt,
|
|
@@ -689,8 +734,49 @@ import { randomUUID } from "crypto";
|
|
|
689
734
|
|
|
690
735
|
// src/run-scenario/agents/claude-code/write-mcp.ts
|
|
691
736
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
692
|
-
import { join as
|
|
737
|
+
import { join as join3 } from "path";
|
|
693
738
|
import { MCP_SERVERS_JSON_KEY } from "@wix/evalforge-types";
|
|
739
|
+
|
|
740
|
+
// src/run-scenario/agents/claude-code/resolve-mcp-placeholders.ts
|
|
741
|
+
import { readFile } from "fs/promises";
|
|
742
|
+
import { join as join2 } from "path";
|
|
743
|
+
import { homedir } from "os";
|
|
744
|
+
var WIX_AUTH_FILE = join2(homedir(), ".wix", "auth", "api-key.json");
|
|
745
|
+
async function loadWixAuthPlaceholders(authFilePath = WIX_AUTH_FILE) {
|
|
746
|
+
try {
|
|
747
|
+
const content = await readFile(authFilePath, "utf-8");
|
|
748
|
+
const auth = JSON.parse(content);
|
|
749
|
+
if (!auth.token || !auth.userInfo?.userId) {
|
|
750
|
+
return {};
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
"wix-auth-token": auth.token,
|
|
754
|
+
"wix-auth-user-id": auth.userInfo.userId
|
|
755
|
+
};
|
|
756
|
+
} catch (err) {
|
|
757
|
+
console.warn(
|
|
758
|
+
`[MCP] Could not load Wix auth file: ${err.message}`
|
|
759
|
+
);
|
|
760
|
+
return {};
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
async function resolveMcpPlaceholders(mcpServers, authFilePath) {
|
|
764
|
+
const needed = findPlaceholders(mcpServers);
|
|
765
|
+
if (needed.length === 0) {
|
|
766
|
+
return mcpServers;
|
|
767
|
+
}
|
|
768
|
+
const placeholders = await loadWixAuthPlaceholders(authFilePath);
|
|
769
|
+
const unresolved = needed.filter((key) => !(key in placeholders));
|
|
770
|
+
if (unresolved.length > 0) {
|
|
771
|
+
throw new Error(
|
|
772
|
+
`MCP config contains unresolvable placeholders: ${unresolved.map((k) => `{{${k}}}`).join(", ")}. Ensure ~/.wix/auth/api-key.json exists (run \`npx @wix/cli login\`).`
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
console.log(`[MCP] Resolved ${needed.length} placeholder(s)`);
|
|
776
|
+
return resolveValue(mcpServers, placeholders);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/run-scenario/agents/claude-code/write-mcp.ts
|
|
694
780
|
async function writeMcpToFilesystem(cwd, mcps) {
|
|
695
781
|
if (mcps.length === 0) return;
|
|
696
782
|
const mcpServers = {};
|
|
@@ -705,19 +791,20 @@ async function writeMcpToFilesystem(cwd, mcps) {
|
|
|
705
791
|
mcpServers[key] = value;
|
|
706
792
|
}
|
|
707
793
|
}
|
|
794
|
+
const resolvedServers = await resolveMcpPlaceholders(mcpServers);
|
|
708
795
|
const content = JSON.stringify(
|
|
709
|
-
{ [MCP_SERVERS_JSON_KEY]:
|
|
796
|
+
{ [MCP_SERVERS_JSON_KEY]: resolvedServers },
|
|
710
797
|
null,
|
|
711
798
|
2
|
|
712
799
|
);
|
|
713
|
-
const filePath =
|
|
800
|
+
const filePath = join3(cwd, ".mcp.json");
|
|
714
801
|
await writeFile2(filePath, content, "utf8");
|
|
715
802
|
console.log(`[MCP] Written to ${filePath}`);
|
|
716
803
|
}
|
|
717
804
|
|
|
718
805
|
// src/run-scenario/agents/claude-code/write-sub-agents.ts
|
|
719
806
|
import { mkdir as mkdir2, writeFile as writeFile3 } from "fs/promises";
|
|
720
|
-
import { join as
|
|
807
|
+
import { join as join4 } from "path";
|
|
721
808
|
var AGENTS_DIR = ".claude/agents";
|
|
722
809
|
function toAgentFilename(name, index, nameCount) {
|
|
723
810
|
const base = (name || "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "") || `sub-agent-${index}`;
|
|
@@ -727,20 +814,20 @@ function toAgentFilename(name, index, nameCount) {
|
|
|
727
814
|
}
|
|
728
815
|
async function writeSubAgentsToFilesystem(cwd, subAgents) {
|
|
729
816
|
if (subAgents.length === 0) return;
|
|
730
|
-
const agentsDir =
|
|
817
|
+
const agentsDir = join4(cwd, AGENTS_DIR);
|
|
731
818
|
await mkdir2(agentsDir, { recursive: true });
|
|
732
819
|
const nameCount = /* @__PURE__ */ new Map();
|
|
733
820
|
for (const [i, agent] of subAgents.entries()) {
|
|
734
821
|
const filename = toAgentFilename(agent.name, i, nameCount);
|
|
735
|
-
const filePath =
|
|
822
|
+
const filePath = join4(agentsDir, `${filename}.md`);
|
|
736
823
|
await writeFile3(filePath, agent.subAgentMd, "utf8");
|
|
737
824
|
}
|
|
738
825
|
console.log(`[SubAgents] Written to ${agentsDir}`);
|
|
739
826
|
}
|
|
740
827
|
|
|
741
828
|
// src/run-scenario/agents/claude-code/write-rules.ts
|
|
742
|
-
import { mkdir as mkdir3, writeFile as writeFile4, readFile } from "fs/promises";
|
|
743
|
-
import { join as
|
|
829
|
+
import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile2 } from "fs/promises";
|
|
830
|
+
import { join as join5 } from "path";
|
|
744
831
|
var CURSOR_RULES_DIR = ".cursor/rules";
|
|
745
832
|
function toRuleFilename(name, index, nameCount) {
|
|
746
833
|
const base = (name || "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "") || `rule-${index}`;
|
|
@@ -751,7 +838,7 @@ function toRuleFilename(name, index, nameCount) {
|
|
|
751
838
|
async function appendToFile(filePath, content) {
|
|
752
839
|
let existing = "";
|
|
753
840
|
try {
|
|
754
|
-
existing = await
|
|
841
|
+
existing = await readFile2(filePath, "utf8");
|
|
755
842
|
} catch {
|
|
756
843
|
}
|
|
757
844
|
const merged = existing ? `${existing.trimEnd()}
|
|
@@ -766,20 +853,20 @@ async function writeRulesToFilesystem(cwd, rules) {
|
|
|
766
853
|
for (const [i, rule] of rules.entries()) {
|
|
767
854
|
switch (rule.ruleType) {
|
|
768
855
|
case "claude-md": {
|
|
769
|
-
await appendToFile(
|
|
856
|
+
await appendToFile(join5(cwd, "CLAUDE.md"), rule.content);
|
|
770
857
|
break;
|
|
771
858
|
}
|
|
772
859
|
case "agents-md": {
|
|
773
|
-
await appendToFile(
|
|
860
|
+
await appendToFile(join5(cwd, "AGENTS.md"), rule.content);
|
|
774
861
|
break;
|
|
775
862
|
}
|
|
776
863
|
case "cursor-rule": {
|
|
777
864
|
if (!hasCursorRules) {
|
|
778
|
-
await mkdir3(
|
|
865
|
+
await mkdir3(join5(cwd, CURSOR_RULES_DIR), { recursive: true });
|
|
779
866
|
hasCursorRules = true;
|
|
780
867
|
}
|
|
781
868
|
const filename = toRuleFilename(rule.name, i, nameCount);
|
|
782
|
-
const filePath =
|
|
869
|
+
const filePath = join5(cwd, CURSOR_RULES_DIR, `${filename}.md`);
|
|
783
870
|
await writeFile4(filePath, rule.content, "utf8");
|
|
784
871
|
break;
|
|
785
872
|
}
|
|
@@ -1815,7 +1902,7 @@ defaultRegistry.register(claudeCodeAdapter);
|
|
|
1815
1902
|
|
|
1816
1903
|
// src/run-scenario/file-diff.ts
|
|
1817
1904
|
import { readdirSync, readFileSync as readFileSync2, statSync, existsSync as existsSync2 } from "fs";
|
|
1818
|
-
import { join as
|
|
1905
|
+
import { join as join7, relative } from "path";
|
|
1819
1906
|
|
|
1820
1907
|
// ../../node_modules/diff/lib/index.mjs
|
|
1821
1908
|
function Diff() {
|
|
@@ -1991,7 +2078,7 @@ Diff.prototype = {
|
|
|
1991
2078
|
tokenize: function tokenize(value) {
|
|
1992
2079
|
return Array.from(value);
|
|
1993
2080
|
},
|
|
1994
|
-
join: function
|
|
2081
|
+
join: function join6(chars) {
|
|
1995
2082
|
return chars.join("");
|
|
1996
2083
|
},
|
|
1997
2084
|
postProcess: function postProcess(changeObjects) {
|
|
@@ -2431,7 +2518,7 @@ function snapshotDirectory(dir, baseDir) {
|
|
|
2431
2518
|
}
|
|
2432
2519
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
2433
2520
|
for (const entry of entries) {
|
|
2434
|
-
const fullPath =
|
|
2521
|
+
const fullPath = join7(dir, entry.name);
|
|
2435
2522
|
const relativePath = relative(base, fullPath);
|
|
2436
2523
|
if (shouldIgnore(entry.name)) {
|
|
2437
2524
|
continue;
|