@wix/evalforge-evaluator 0.159.0 → 0.161.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
@@ -821,6 +821,29 @@ async function appendToFile(filePath, content) {
821
821
  ${content}` : content;
822
822
  await (0, import_promises6.writeFile)(filePath, merged, "utf8");
823
823
  }
824
+ function validateGenericDirectory(dir, cwd) {
825
+ const trimmed = dir.trim();
826
+ if (!trimmed) {
827
+ throw new Error(`Generic rule directory must not be empty`);
828
+ }
829
+ if (trimmed.startsWith("/") || trimmed.startsWith("\\") || trimmed.startsWith("~")) {
830
+ throw new Error(`Generic rule directory must be relative, got: "${dir}"`);
831
+ }
832
+ const segments = trimmed.split(/[\\/]/);
833
+ if (segments.some((s) => s === "..")) {
834
+ throw new Error(
835
+ `Generic rule directory may not contain "..", got: "${dir}"`
836
+ );
837
+ }
838
+ const normalizedCwd = cwd.endsWith(import_path7.sep) ? cwd.slice(0, -1) : cwd;
839
+ const resolved = (0, import_path7.resolve)(normalizedCwd, trimmed);
840
+ if (!resolved.startsWith(normalizedCwd + import_path7.sep)) {
841
+ throw new Error(
842
+ `Generic rule directory escapes the working directory: "${dir}"`
843
+ );
844
+ }
845
+ return trimmed;
846
+ }
824
847
  async function writeRulesToFilesystem(cwd, rules) {
825
848
  if (rules.length === 0) return;
826
849
  const nameCount = /* @__PURE__ */ new Map();
@@ -845,6 +868,21 @@ async function writeRulesToFilesystem(cwd, rules) {
845
868
  await (0, import_promises6.writeFile)(filePath, rule.content, "utf8");
846
869
  break;
847
870
  }
871
+ case "generic": {
872
+ const directory = validateGenericDirectory(
873
+ rule.directory ?? ".opencode/rules",
874
+ cwd
875
+ );
876
+ const dirPath = (0, import_path7.join)(cwd, directory);
877
+ await (0, import_promises6.mkdir)(dirPath, { recursive: true });
878
+ const filename = toRuleFilename(rule.name, i, nameCount);
879
+ await (0, import_promises6.writeFile)((0, import_path7.join)(dirPath, `${filename}.md`), rule.content, "utf8");
880
+ break;
881
+ }
882
+ default: {
883
+ const _exhaustive = rule.ruleType;
884
+ throw new Error(`Unhandled ruleType: ${_exhaustive}`);
885
+ }
848
886
  }
849
887
  }
850
888
  console.log(`[Rules] Written ${rules.length} rule(s) to ${cwd}`);
@@ -2366,12 +2404,25 @@ async function buildOpenCodeEnv(options) {
2366
2404
  ...defaultPermission,
2367
2405
  ...configPermission
2368
2406
  };
2407
+ let instructions;
2408
+ if (options.rules && options.rules.length > 0) {
2409
+ const genericDirs = /* @__PURE__ */ new Set();
2410
+ for (const rule of options.rules) {
2411
+ if (rule.ruleType === "generic") {
2412
+ genericDirs.add(rule.directory ?? ".opencode/rules");
2413
+ }
2414
+ }
2415
+ if (genericDirs.size > 0) {
2416
+ instructions = Array.from(genericDirs).sort().map((d) => `${d}/*.md`);
2417
+ }
2418
+ }
2369
2419
  const config = {
2370
2420
  model: `${providerID}/${modelID}`,
2371
2421
  provider,
2372
2422
  ...Object.keys(agentOverrides).length > 0 ? { agent: { build: agentOverrides } } : {},
2373
2423
  permission,
2374
- ...mcp ? { mcp } : {}
2424
+ ...mcp ? { mcp } : {},
2425
+ ...instructions ? { instructions } : {}
2375
2426
  };
2376
2427
  const env = {
2377
2428
  ...process.env,
@@ -2886,7 +2937,7 @@ function spawnOpenCodeProcess(opts) {
2886
2937
  traceContext,
2887
2938
  initialStepNumber
2888
2939
  } = opts;
2889
- return new Promise((resolve2) => {
2940
+ return new Promise((resolve3) => {
2890
2941
  let resolved = false;
2891
2942
  let stderr = "";
2892
2943
  let lineBuffer = "";
@@ -2906,7 +2957,7 @@ function spawnOpenCodeProcess(opts) {
2906
2957
  if (resolved) return;
2907
2958
  resolved = true;
2908
2959
  cleanup();
2909
- resolve2({
2960
+ resolve3({
2910
2961
  events,
2911
2962
  success,
2912
2963
  isIdleTimeout,
@@ -2923,7 +2974,7 @@ function spawnOpenCodeProcess(opts) {
2923
2974
  detached: true
2924
2975
  });
2925
2976
  } catch (spawnError) {
2926
- resolve2({
2977
+ resolve3({
2927
2978
  events: [],
2928
2979
  success: false,
2929
2980
  isIdleTimeout: false,
@@ -3114,6 +3165,7 @@ async function executeWithOpenCode(skills, scenario, options) {
3114
3165
  aiGatewayUrl: options.aiGatewayUrl,
3115
3166
  aiGatewayHeaders: options.aiGatewayHeaders,
3116
3167
  mcps: options.mcps,
3168
+ rules: options.rules,
3117
3169
  cwd: options.cwd,
3118
3170
  config: options.config
3119
3171
  });
@@ -3861,6 +3913,19 @@ async function executeWithAiSdk(context) {
3861
3913
  } catch (err) {
3862
3914
  const baseMsg = err instanceof Error ? err.message : String(err);
3863
3915
  const ctx = extractGatewayErrorContext(err);
3916
+ const apiError = findApiCallError(err);
3917
+ console.error(
3918
+ "[AI gateway error]",
3919
+ JSON.stringify({
3920
+ provider,
3921
+ model: modelId,
3922
+ message: baseMsg,
3923
+ statusCode: apiError?.statusCode,
3924
+ xWixRequestId: getHeader(apiError?.responseHeaders, "x-wix-request-id"),
3925
+ proxyRequestId: getProxyBodyFields(apiError?.responseBody).proxy_request_id,
3926
+ failurePhase: getProxyBodyFields(apiError?.responseBody).failure_phase
3927
+ })
3928
+ );
3864
3929
  throw new Error(
3865
3930
  `AI gateway request failed (provider=${provider}, model=${modelId}): ${baseMsg}${ctx}`,
3866
3931
  { cause: err }