@hasna/testers 0.0.35 → 0.0.36

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/index.js CHANGED
@@ -13983,6 +13983,10 @@ function loadConfig() {
13983
13983
  if (envApiKey) {
13984
13984
  config.anthropicApiKey = envApiKey;
13985
13985
  }
13986
+ const envSelfHeal = process.env["TESTERS_SELF_HEAL"];
13987
+ if (envSelfHeal !== undefined) {
13988
+ config.selfHeal = ["1", "true", "yes", "on"].includes(envSelfHeal.toLowerCase());
13989
+ }
13986
13990
  return config;
13987
13991
  }
13988
13992
  var CONFIG_DIR3, CONFIG_PATH2;
@@ -14019,12 +14023,11 @@ Original selector that failed: "${request.failedSelector}"
14019
14023
  Please identify the correct selector from the screenshot.`;
14020
14024
  let rawResponse = "";
14021
14025
  try {
14022
- if (provider === "openai" || provider === "google") {
14023
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
14024
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
14026
+ if (provider !== "anthropic") {
14027
+ const compat = createOpenAICompatibleConfig(provider);
14025
14028
  const resp = await callOpenAICompatible({
14026
- baseUrl,
14027
- apiKey,
14029
+ baseUrl: compat.baseUrl,
14030
+ apiKey: compat.apiKey,
14028
14031
  model,
14029
14032
  system: HEAL_SYSTEM,
14030
14033
  messages: [{ role: "user", content: userMessage }],
@@ -14118,9 +14121,11 @@ var init_healer = __esm(() => {
14118
14121
  var exports_ai_client = {};
14119
14122
  __export(exports_ai_client, {
14120
14123
  runAgentLoop: () => runAgentLoop,
14124
+ resolveProviderApiKeyForModel: () => resolveProviderApiKeyForModel,
14121
14125
  resolveModel: () => resolveModel,
14122
14126
  executeTool: () => executeTool,
14123
14127
  detectProvider: () => detectProvider,
14128
+ createOpenAICompatibleConfig: () => createOpenAICompatibleConfig,
14124
14129
  createClientForModel: () => createClientForModel,
14125
14130
  createClient: () => createClient,
14126
14131
  callOpenAICompatible: () => callOpenAICompatible,
@@ -14943,10 +14948,17 @@ function detectProvider(model) {
14943
14948
  return "openai";
14944
14949
  if (model.startsWith("gemini-"))
14945
14950
  return "google";
14951
+ if (model.startsWith("glm-") || model.startsWith("zai/") || model.startsWith("zai-"))
14952
+ return "zai";
14946
14953
  if (model.startsWith("llama-") || model.startsWith("qwen-") || model.includes("cerebras"))
14947
14954
  return "cerebras";
14948
14955
  return "anthropic";
14949
14956
  }
14957
+ function resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
14958
+ if (explicitApiKey)
14959
+ return explicitApiKey;
14960
+ return detectProvider(model) === "anthropic" ? configuredAnthropicApiKey : undefined;
14961
+ }
14950
14962
  function createClient(apiKey) {
14951
14963
  const key = apiKey ?? process.env["ANTHROPIC_API_KEY"];
14952
14964
  if (!key) {
@@ -15024,26 +15036,34 @@ async function callOpenAICompatible(options) {
15024
15036
  const usage = { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0 };
15025
15037
  return { content, stop_reason: stopReason, usage };
15026
15038
  }
15027
- function createClientForModel(model, apiKey) {
15028
- const provider = detectProvider(model);
15039
+ function createOpenAICompatibleConfig(provider, apiKey) {
15029
15040
  if (provider === "openai") {
15030
- const key = apiKey ?? process.env["OPENAI_API_KEY"];
15031
- if (!key)
15041
+ const key2 = apiKey ?? process.env["OPENAI_API_KEY"];
15042
+ if (!key2)
15032
15043
  throw new AIClientError("No OpenAI API key. Set OPENAI_API_KEY or pass it explicitly.");
15033
- return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key };
15044
+ return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key2 };
15034
15045
  }
15035
15046
  if (provider === "google") {
15036
- const key = apiKey ?? process.env["GOOGLE_API_KEY"];
15037
- if (!key)
15047
+ const key2 = apiKey ?? process.env["GOOGLE_API_KEY"];
15048
+ if (!key2)
15038
15049
  throw new AIClientError("No Google API key. Set GOOGLE_API_KEY or pass it explicitly.");
15039
- return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key };
15050
+ return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key2 };
15040
15051
  }
15041
15052
  if (provider === "cerebras") {
15042
- const key = apiKey ?? process.env["CEREBRAS_API_KEY"];
15043
- if (!key)
15053
+ const key2 = apiKey ?? process.env["CEREBRAS_API_KEY"];
15054
+ if (!key2)
15044
15055
  throw new AIClientError("No Cerebras API key. Set CEREBRAS_API_KEY or pass it explicitly.");
15045
- return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key };
15056
+ return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key2 };
15046
15057
  }
15058
+ const key = apiKey ?? process.env["ZAI_API_KEY"];
15059
+ if (!key)
15060
+ throw new AIClientError("No Z.AI API key. Set ZAI_API_KEY or pass it explicitly.");
15061
+ return { provider: "zai", baseUrl: "https://api.z.ai/api/paas/v4", apiKey: key };
15062
+ }
15063
+ function createClientForModel(model, apiKey) {
15064
+ const provider = detectProvider(model);
15065
+ if (provider !== "anthropic")
15066
+ return createOpenAICompatibleConfig(provider, apiKey);
15047
15067
  return createClient(apiKey);
15048
15068
  }
15049
15069
  var activeHARs, activeCoverage, BROWSER_TOOLS;
@@ -15620,22 +15640,22 @@ function resolveJudgeModel(config) {
15620
15640
  apiKey = process.env["GOOGLE_API_KEY"];
15621
15641
  else if (provider === "cerebras")
15622
15642
  apiKey = process.env["CEREBRAS_API_KEY"];
15643
+ else if (provider === "zai")
15644
+ apiKey = process.env["ZAI_API_KEY"];
15623
15645
  }
15624
15646
  if (!apiKey) {
15625
- apiKey = process.env["ANTHROPIC_API_KEY"] ?? process.env["CEREBRAS_API_KEY"] ?? process.env["OPENAI_API_KEY"] ?? process.env["GOOGLE_API_KEY"] ?? globalConfig.anthropicApiKey;
15626
- if (!apiKey)
15627
- throw new AIClientError("No API key found for judge. Set ANTHROPIC_API_KEY, CEREBRAS_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY.");
15647
+ throw new AIClientError(`No API key found for ${provider} judge provider.`);
15628
15648
  }
15629
15649
  return { model, provider, apiKey };
15630
15650
  }
15631
15651
  async function callJudge(prompt, config) {
15632
15652
  const { model, provider, apiKey } = resolveJudgeModel(config);
15633
15653
  const threshold = 0.7;
15634
- if (provider === "openai" || provider === "google" || provider === "cerebras") {
15635
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : provider === "cerebras" ? "https://api.cerebras.ai/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
15654
+ if (provider !== "anthropic") {
15655
+ const compat = createOpenAICompatibleConfig(provider, apiKey);
15636
15656
  const resp2 = await callOpenAICompatible({
15637
- baseUrl,
15638
- apiKey,
15657
+ baseUrl: compat.baseUrl,
15658
+ apiKey: compat.apiKey,
15639
15659
  model,
15640
15660
  system: LLM_SYSTEM,
15641
15661
  messages: [{ role: "user", content: prompt }],
@@ -18117,6 +18137,7 @@ __export(exports_runner, {
18117
18137
  runByFilter: () => runByFilter,
18118
18138
  runBatch: () => runBatch,
18119
18139
  resolveScenariosForRun: () => resolveScenariosForRun,
18140
+ resolveAgentApiKeyForModel: () => resolveAgentApiKeyForModel,
18120
18141
  onRunEvent: () => onRunEvent,
18121
18142
  applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
18122
18143
  });
@@ -18130,6 +18151,9 @@ function emit(event) {
18130
18151
  if (eventHandler)
18131
18152
  eventHandler(event);
18132
18153
  }
18154
+ function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
18155
+ return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
18156
+ }
18133
18157
  function assertionDescription(result) {
18134
18158
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
18135
18159
  }
@@ -18238,7 +18262,7 @@ async function runSingleScenario(scenario, runId, options) {
18238
18262
  });
18239
18263
  }
18240
18264
  }
18241
- const client = createClientForModel(model, effectiveOptions.apiKey ?? config.anthropicApiKey);
18265
+ const client = createClientForModel(model, resolveAgentApiKeyForModel(model, effectiveOptions.apiKey, config.anthropicApiKey));
18242
18266
  const screenshotter = new Screenshotter({
18243
18267
  baseDir: effectiveOptions.screenshotDir ?? config.screenshots.dir
18244
18268
  });
@@ -26313,12 +26337,28 @@ Rules:
26313
26337
  ];
26314
26338
  const messages = [{ role: "user", content: contentParts }];
26315
26339
  try {
26316
- const response = await anthropicClient.messages.create({
26317
- model,
26318
- max_tokens: 2048,
26319
- messages
26320
- });
26321
- const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
26340
+ let text;
26341
+ const provider = detectProvider(model);
26342
+ if (provider !== "anthropic") {
26343
+ const compat = client;
26344
+ const response = await callOpenAICompatible({
26345
+ baseUrl: compat.baseUrl,
26346
+ apiKey: compat.apiKey,
26347
+ model,
26348
+ system: "You are a QA engineer.",
26349
+ messages: [{ role: "user", content: prompt }],
26350
+ tools: [],
26351
+ maxTokens: 2048
26352
+ });
26353
+ text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
26354
+ } else {
26355
+ const response = await anthropicClient.messages.create({
26356
+ model,
26357
+ max_tokens: 2048,
26358
+ messages
26359
+ });
26360
+ text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
26361
+ }
26322
26362
  const match = text.match(/\[[\s\S]*\]/);
26323
26363
  if (!match)
26324
26364
  return [];
@@ -26346,7 +26386,7 @@ async function crawlAndGenerate(options) {
26346
26386
  } = options;
26347
26387
  const config = loadConfig();
26348
26388
  const model = resolveModel(options.model ?? config.defaultModel ?? "thorough");
26349
- const client = createClient(options.apiKey ?? config.anthropicApiKey);
26389
+ const client = createClientForModel(model, resolveProviderApiKeyForModel(model, options.apiKey, config.anthropicApiKey));
26350
26390
  const rootOrigin = new URL(url).origin;
26351
26391
  const visited = new Set;
26352
26392
  const queue = [url];
@@ -26426,7 +26466,6 @@ var init_crawl_and_generate = __esm(() => {
26426
26466
  init_scenarios();
26427
26467
  init_ai_client();
26428
26468
  init_config2();
26429
- init_ai_client();
26430
26469
  DEFAULT_SKIP_PATTERNS = [
26431
26470
  "/logout",
26432
26471
  "/sign-out",
@@ -57815,12 +57854,11 @@ APP STRUCTURE:
57815
57854
  ${summary}`;
57816
57855
  let rawText = "";
57817
57856
  let tokensUsed = 0;
57818
- if (provider === "openai" || provider === "google") {
57819
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
57820
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
57857
+ if (provider !== "anthropic") {
57858
+ const compat = createOpenAICompatibleConfig(provider);
57821
57859
  const resp = await callOpenAICompatible({
57822
- baseUrl,
57823
- apiKey,
57860
+ baseUrl: compat.baseUrl,
57861
+ apiKey: compat.apiKey,
57824
57862
  model,
57825
57863
  system: GENERATOR_SYSTEM,
57826
57864
  messages: [{ role: "user", content: prompt }],
@@ -93415,9 +93453,9 @@ async function convertSessionToScenario(events, options) {
93415
93453
  const name21 = options?.name ?? `Recorded session ${new Date().toISOString().slice(0, 10)}`;
93416
93454
  const targetPath = extractTargetPath(events);
93417
93455
  let steps;
93418
- if (options?.model && (process.env["ANTHROPIC_API_KEY"] || process.env["OPENAI_API_KEY"] || process.env["GOOGLE_API_KEY"])) {
93456
+ if (options?.model && (process.env["ANTHROPIC_API_KEY"] || process.env["OPENAI_API_KEY"] || process.env["GOOGLE_API_KEY"] || process.env["CEREBRAS_API_KEY"] || process.env["ZAI_API_KEY"])) {
93419
93457
  try {
93420
- const { callOpenAICompatible: callOpenAICompatible2, detectProvider: detectProvider2 } = await Promise.resolve().then(() => (init_ai_client(), exports_ai_client));
93458
+ const { callOpenAICompatible: callOpenAICompatible2, createOpenAICompatibleConfig: createOpenAICompatibleConfig2, detectProvider: detectProvider2 } = await Promise.resolve().then(() => (init_ai_client(), exports_ai_client));
93421
93459
  const model = options.model;
93422
93460
  const provider = detectProvider2(model);
93423
93461
  const condensed = events.filter((e2) => e2.type !== "network").map((e2) => `[${e2.type}] ${e2.url ?? e2.selector ?? e2.value ?? ""}`).slice(0, 100).join(`
@@ -93427,10 +93465,9 @@ async function convertSessionToScenario(events, options) {
93427
93465
  Events:
93428
93466
  ${condensed}`;
93429
93467
  let rawText = "";
93430
- if (provider === "openai" || provider === "google") {
93431
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
93432
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
93433
- const resp = await callOpenAICompatible2({ baseUrl, apiKey, model, system: "You are a QA engineer.", messages: [{ role: "user", content: prompt }], tools: [], maxTokens: 1024 });
93468
+ if (provider !== "anthropic") {
93469
+ const compat2 = createOpenAICompatibleConfig2(provider);
93470
+ const resp = await callOpenAICompatible2({ baseUrl: compat2.baseUrl, apiKey: compat2.apiKey, model, system: "You are a QA engineer.", messages: [{ role: "user", content: prompt }], tools: [], maxTokens: 1024 });
93434
93471
  const block = resp.content.find((b2) => b2.type === "text");
93435
93472
  rawText = block?.text ?? "";
93436
93473
  } else {
@@ -93826,7 +93863,7 @@ async function runHybridScenario(scenario, options) {
93826
93863
  const stepStart = Date.now();
93827
93864
  if (step.type === "ai" || step.type === "ai_verify") {
93828
93865
  const model = resolveModel(step.model ?? scenario.model ?? config2.defaultModel);
93829
- const client = createClientForModel(model, options?.apiKey ?? config2.anthropicApiKey);
93866
+ const client = createClientForModel(model, resolveProviderApiKeyForModel(model, options?.apiKey, config2.anthropicApiKey));
93830
93867
  const instruction = step.type === "ai_verify" ? `Verify the following assertion about the current page state: "${step.assertion}". Do NOT navigate. Just inspect the page and call report_result with pass or fail.` : step.instruction;
93831
93868
  const syntheticScenario = {
93832
93869
  id: `hybrid-step-${i2}`,
@@ -93943,7 +93980,7 @@ import chalk6 from "chalk";
93943
93980
  // package.json
93944
93981
  var package_default = {
93945
93982
  name: "@hasna/testers",
93946
- version: "0.0.35",
93983
+ version: "0.0.36",
93947
93984
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
93948
93985
  type: "module",
93949
93986
  main: "dist/index.js",
@@ -97284,8 +97321,9 @@ program2.command("run [url] [description]").alias("test").description("Run test
97284
97321
  const hasOpenAI = Boolean(process.env["OPENAI_API_KEY"]);
97285
97322
  const hasGoogle = Boolean(process.env["GOOGLE_API_KEY"]);
97286
97323
  const hasCerebras = Boolean(process.env["CEREBRAS_API_KEY"]);
97287
- if (!hasAnthropic && !hasOpenAI && !hasGoogle && !hasCerebras) {
97288
- logError(chalk6.red("No AI API key found. Set ANTHROPIC_API_KEY (recommended), or OPENAI_API_KEY / GOOGLE_API_KEY / CEREBRAS_API_KEY."));
97324
+ const hasZai = Boolean(process.env["ZAI_API_KEY"]);
97325
+ if (!hasAnthropic && !hasOpenAI && !hasGoogle && !hasCerebras && !hasZai) {
97326
+ logError(chalk6.red("No AI API key found. Set ANTHROPIC_API_KEY (recommended), or OPENAI_API_KEY / GOOGLE_API_KEY / CEREBRAS_API_KEY / ZAI_API_KEY."));
97289
97327
  logError(chalk6.red("For GitHub Actions, add ANTHROPIC_API_KEY to your repo secrets and pass it via: env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}"));
97290
97328
  process.exit(2);
97291
97329
  }
@@ -99813,11 +99851,13 @@ program2.command("doctor").description("Check system setup and configuration").a
99813
99851
  const openaiKey = !!process.env["OPENAI_API_KEY"];
99814
99852
  const googleKey = !!process.env["GOOGLE_API_KEY"];
99815
99853
  const cerebrasKey = !!process.env["CEREBRAS_API_KEY"];
99854
+ const zaiKey = !!process.env["ZAI_API_KEY"];
99816
99855
  log((anthropicKey ? chalk6.green(" \u2713") : chalk6.red(" \u2717")) + ` Anthropic (ANTHROPIC_API_KEY)${!anthropicKey ? " \u2014 required for default model" : ""}`);
99817
99856
  log((openaiKey ? chalk6.green(" \u2713") : chalk6.dim(" \u25CB")) + ` OpenAI (OPENAI_API_KEY) \u2014 optional, enables gpt-* models`);
99818
99857
  log((googleKey ? chalk6.green(" \u2713") : chalk6.dim(" \u25CB")) + ` Google Gemini (GOOGLE_API_KEY) \u2014 optional, enables gemini-* models`);
99819
99858
  log((cerebrasKey ? chalk6.green(" \u2713") : chalk6.dim(" \u25CB")) + ` Cerebras (CEREBRAS_API_KEY) \u2014 optional, enables llama-*/qwen-* at ~20x faster inference`);
99820
- if (!anthropicKey && !openaiKey && !googleKey && !cerebrasKey) {
99859
+ log((zaiKey ? chalk6.green(" \u2713") : chalk6.dim(" \u25CB")) + ` Z.AI (ZAI_API_KEY) \u2014 optional, enables glm-* models such as glm-5.1`);
99860
+ if (!anthropicKey && !openaiKey && !googleKey && !cerebrasKey && !zaiKey) {
99821
99861
  log(chalk6.red(" \u2717") + " No AI provider API keys found \u2014 at least one is required");
99822
99862
  allPassed = false;
99823
99863
  }
package/dist/index.js CHANGED
@@ -10735,6 +10735,10 @@ function loadConfig() {
10735
10735
  if (envApiKey) {
10736
10736
  config.anthropicApiKey = envApiKey;
10737
10737
  }
10738
+ const envSelfHeal = process.env["TESTERS_SELF_HEAL"];
10739
+ if (envSelfHeal !== undefined) {
10740
+ config.selfHeal = ["1", "true", "yes", "on"].includes(envSelfHeal.toLowerCase());
10741
+ }
10738
10742
  return config;
10739
10743
  }
10740
10744
  function resolveModel(nameOrId) {
@@ -11652,12 +11656,11 @@ Original selector that failed: "${request.failedSelector}"
11652
11656
  Please identify the correct selector from the screenshot.`;
11653
11657
  let rawResponse = "";
11654
11658
  try {
11655
- if (provider === "openai" || provider === "google") {
11656
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
11657
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
11659
+ if (provider !== "anthropic") {
11660
+ const compat = createOpenAICompatibleConfig(provider);
11658
11661
  const resp = await callOpenAICompatible({
11659
- baseUrl,
11660
- apiKey,
11662
+ baseUrl: compat.baseUrl,
11663
+ apiKey: compat.apiKey,
11661
11664
  model,
11662
11665
  system: HEAL_SYSTEM,
11663
11666
  messages: [{ role: "user", content: userMessage }],
@@ -12564,10 +12567,17 @@ function detectProvider(model) {
12564
12567
  return "openai";
12565
12568
  if (model.startsWith("gemini-"))
12566
12569
  return "google";
12570
+ if (model.startsWith("glm-") || model.startsWith("zai/") || model.startsWith("zai-"))
12571
+ return "zai";
12567
12572
  if (model.startsWith("llama-") || model.startsWith("qwen-") || model.includes("cerebras"))
12568
12573
  return "cerebras";
12569
12574
  return "anthropic";
12570
12575
  }
12576
+ function resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
12577
+ if (explicitApiKey)
12578
+ return explicitApiKey;
12579
+ return detectProvider(model) === "anthropic" ? configuredAnthropicApiKey : undefined;
12580
+ }
12571
12581
  function createClient(apiKey) {
12572
12582
  const key = apiKey ?? process.env["ANTHROPIC_API_KEY"];
12573
12583
  if (!key) {
@@ -12645,26 +12655,34 @@ async function callOpenAICompatible(options) {
12645
12655
  const usage = { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0 };
12646
12656
  return { content, stop_reason: stopReason, usage };
12647
12657
  }
12648
- function createClientForModel(model, apiKey) {
12649
- const provider = detectProvider(model);
12658
+ function createOpenAICompatibleConfig(provider, apiKey) {
12650
12659
  if (provider === "openai") {
12651
- const key = apiKey ?? process.env["OPENAI_API_KEY"];
12652
- if (!key)
12660
+ const key2 = apiKey ?? process.env["OPENAI_API_KEY"];
12661
+ if (!key2)
12653
12662
  throw new AIClientError("No OpenAI API key. Set OPENAI_API_KEY or pass it explicitly.");
12654
- return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key };
12663
+ return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key2 };
12655
12664
  }
12656
12665
  if (provider === "google") {
12657
- const key = apiKey ?? process.env["GOOGLE_API_KEY"];
12658
- if (!key)
12666
+ const key2 = apiKey ?? process.env["GOOGLE_API_KEY"];
12667
+ if (!key2)
12659
12668
  throw new AIClientError("No Google API key. Set GOOGLE_API_KEY or pass it explicitly.");
12660
- return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key };
12669
+ return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key2 };
12661
12670
  }
12662
12671
  if (provider === "cerebras") {
12663
- const key = apiKey ?? process.env["CEREBRAS_API_KEY"];
12664
- if (!key)
12672
+ const key2 = apiKey ?? process.env["CEREBRAS_API_KEY"];
12673
+ if (!key2)
12665
12674
  throw new AIClientError("No Cerebras API key. Set CEREBRAS_API_KEY or pass it explicitly.");
12666
- return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key };
12675
+ return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key2 };
12667
12676
  }
12677
+ const key = apiKey ?? process.env["ZAI_API_KEY"];
12678
+ if (!key)
12679
+ throw new AIClientError("No Z.AI API key. Set ZAI_API_KEY or pass it explicitly.");
12680
+ return { provider: "zai", baseUrl: "https://api.z.ai/api/paas/v4", apiKey: key };
12681
+ }
12682
+ function createClientForModel(model, apiKey) {
12683
+ const provider = detectProvider(model);
12684
+ if (provider !== "anthropic")
12685
+ return createOpenAICompatibleConfig(provider, apiKey);
12668
12686
  return createClient(apiKey);
12669
12687
  }
12670
12688
  var activeHARs, activeCoverage, BROWSER_TOOLS;
@@ -14103,11 +14121,11 @@ function resolveJudgeModel(config) {
14103
14121
  apiKey = process.env["GOOGLE_API_KEY"];
14104
14122
  else if (provider === "cerebras")
14105
14123
  apiKey = process.env["CEREBRAS_API_KEY"];
14124
+ else if (provider === "zai")
14125
+ apiKey = process.env["ZAI_API_KEY"];
14106
14126
  }
14107
14127
  if (!apiKey) {
14108
- apiKey = process.env["ANTHROPIC_API_KEY"] ?? process.env["CEREBRAS_API_KEY"] ?? process.env["OPENAI_API_KEY"] ?? process.env["GOOGLE_API_KEY"] ?? globalConfig.anthropicApiKey;
14109
- if (!apiKey)
14110
- throw new AIClientError("No API key found for judge. Set ANTHROPIC_API_KEY, CEREBRAS_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY.");
14128
+ throw new AIClientError(`No API key found for ${provider} judge provider.`);
14111
14129
  }
14112
14130
  return { model, provider, apiKey };
14113
14131
  }
@@ -14122,11 +14140,11 @@ reason: 1-2 sentences max`;
14122
14140
  async function callJudge(prompt, config) {
14123
14141
  const { model, provider, apiKey } = resolveJudgeModel(config);
14124
14142
  const threshold = 0.7;
14125
- if (provider === "openai" || provider === "google" || provider === "cerebras") {
14126
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : provider === "cerebras" ? "https://api.cerebras.ai/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
14143
+ if (provider !== "anthropic") {
14144
+ const compat = createOpenAICompatibleConfig(provider, apiKey);
14127
14145
  const resp2 = await callOpenAICompatible({
14128
- baseUrl,
14129
- apiKey,
14146
+ baseUrl: compat.baseUrl,
14147
+ apiKey: compat.apiKey,
14130
14148
  model,
14131
14149
  system: LLM_SYSTEM,
14132
14150
  messages: [{ role: "user", content: prompt }],
@@ -16413,6 +16431,9 @@ function emit(event) {
16413
16431
  if (eventHandler)
16414
16432
  eventHandler(event);
16415
16433
  }
16434
+ function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
16435
+ return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
16436
+ }
16416
16437
  function assertionDescription(result) {
16417
16438
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
16418
16439
  }
@@ -16521,7 +16542,7 @@ async function runSingleScenario(scenario, runId, options) {
16521
16542
  });
16522
16543
  }
16523
16544
  }
16524
- const client = createClientForModel(model, effectiveOptions.apiKey ?? config.anthropicApiKey);
16545
+ const client = createClientForModel(model, resolveAgentApiKeyForModel(model, effectiveOptions.apiKey, config.anthropicApiKey));
16525
16546
  const screenshotter = new Screenshotter({
16526
16547
  baseDir: effectiveOptions.screenshotDir ?? config.screenshots.dir
16527
16548
  });
@@ -96,9 +96,13 @@ export declare function runAgentLoop(options: AgentLoopOptions): Promise<AgentLo
96
96
  * Detects the AI provider from a model name.
97
97
  * - "gpt-*" or "o1-*" / "o3-*" → openai
98
98
  * - "gemini-*" → google
99
+ * - "glm-*" / "zai/*" / "zai-*" → Z.AI
100
+ * - "llama-*" / "qwen-*" / names containing "cerebras" → Cerebras
99
101
  * - everything else → anthropic (default)
100
102
  */
101
- export declare function detectProvider(model: string): "anthropic" | "openai" | "google" | "cerebras";
103
+ export type AIProvider = "anthropic" | "openai" | "google" | "cerebras" | "zai";
104
+ export declare function detectProvider(model: string): AIProvider;
105
+ export declare function resolveProviderApiKeyForModel(model: string, explicitApiKey?: string, configuredAnthropicApiKey?: string): string | undefined;
102
106
  /**
103
107
  * Creates an Anthropic client instance. Uses the provided API key,
104
108
  * or falls back to the ANTHROPIC_API_KEY environment variable.
@@ -128,11 +132,13 @@ export declare function callOpenAICompatible(options: {
128
132
  * Creates the right client/config for a given model. Returns either an Anthropic
129
133
  * client or a config object for the OpenAI-compatible path.
130
134
  */
135
+ export type OpenAICompatProvider = Exclude<AIProvider, "anthropic">;
131
136
  export type OpenAICompatConfig = {
132
- provider: "openai" | "google" | "cerebras";
137
+ provider: OpenAICompatProvider;
133
138
  baseUrl: string;
134
139
  apiKey: string;
135
140
  };
141
+ export declare function createOpenAICompatibleConfig(provider: OpenAICompatProvider, apiKey?: string): OpenAICompatConfig;
136
142
  export declare function createClientForModel(model: string, apiKey?: string): Anthropic | OpenAICompatConfig;
137
143
  export {};
138
144
  //# sourceMappingURL=ai-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-client.d.ts","sourceRoot":"","sources":["../../src/lib/ai-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ai-client.d.ts","sourceRoot":"","sources":["../../src/lib/ai-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAOpE;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAiBhD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAkD1C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKrD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAOpE;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAiBhD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAuD1C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKrD"}
@@ -4,7 +4,7 @@
4
4
  * Given any URL:
5
5
  * 1. Crawls the app with a headless browser to discover pages
6
6
  * 2. Visits each page, captures a screenshot + simplified HTML
7
- * 3. Sends both to Claude with a prompt to write test scenarios
7
+ * 3. Sends the page context to the configured model to write test scenarios
8
8
  * 4. Creates the scenarios in the DB under the given project
9
9
  *
10
10
  * Works for any web app — no manual setup required.
@@ -1 +1 @@
1
- {"version":3,"file":"crawl-and-generate.d.ts","sourceRoot":"","sources":["../../src/lib/crawl-and-generate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAwJD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAuGxG"}
1
+ {"version":3,"file":"crawl-and-generate.d.ts","sourceRoot":"","sources":["../../src/lib/crawl-and-generate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AA2KD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0GxG"}
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/lib/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,mBAAmB,CAAC;AAI/E,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AA6KD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoD3F"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/lib/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,mBAAmB,CAAC;AAI/E,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAyKD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoD3F"}
@@ -1 +1 @@
1
- {"version":3,"file":"healer.d.ts","sourceRoot":"","sources":["../../src/lib/healer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAQvC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAmBD,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6G5E"}
1
+ {"version":3,"file":"healer.d.ts","sourceRoot":"","sources":["../../src/lib/healer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAQvC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAmBD,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyG5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"hybrid-runner.d.ts","sourceRoot":"","sources":["../../src/lib/hybrid-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hybrid-runner.d.ts","sourceRoot":"","sources":["../../src/lib/hybrid-runner.ts"],"names":[],"mappings":"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"}
@@ -7,10 +7,10 @@
7
7
  * Provider resolution order:
8
8
  * 1. config.model (explicit) → detectProvider()
9
9
  * 2. ANTHROPIC_API_KEY env
10
- * 3. OPENAI_API_KEY env
11
- * 4. GOOGLE_API_KEY env
10
+ * 3. OPENAI_API_KEY / GOOGLE_API_KEY / CEREBRAS_API_KEY / ZAI_API_KEY env
12
11
  */
13
- export type JudgeProvider = "anthropic" | "openai" | "google" | "cerebras" | "auto";
12
+ import { type AIProvider } from "./ai-client.js";
13
+ export type JudgeProvider = AIProvider | "auto";
14
14
  export interface JudgeConfig {
15
15
  model?: string;
16
16
  provider?: JudgeProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"judge.d.ts","sourceRoot":"","sources":["../../src/lib/judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAEpF,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAsID,wBAAsB,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAwCzF;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAMpG"}
1
+ {"version":3,"file":"judge.d.ts","sourceRoot":"","sources":["../../src/lib/judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAIL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAOxB,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAkID,wBAAsB,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAwCzF;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAMpG"}
@@ -46,6 +46,7 @@ export interface RunEvent {
46
46
  }
47
47
  export type RunEventHandler = (event: RunEvent) => void;
48
48
  export declare function onRunEvent(handler: RunEventHandler): void;
49
+ export declare function resolveAgentApiKeyForModel(model: string, explicitApiKey?: string, configuredAnthropicApiKey?: string): string | undefined;
49
50
  type AgentScenarioStatus = Extract<ResultStatus, "passed" | "failed" | "error">;
50
51
  export interface StructuredAssertionOutcome {
51
52
  status: AgentScenarioStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA6B7E,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,mBAAmB,EAAE,aAAa,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,CAAA;KAAE,CAAC;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EACA,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,qBAAqB,GACrB,cAAc,GACd,gBAAgB,GAChB,kBAAkB,GAClB,eAAe,GACf,0BAA0B,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAIxD,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAEzD;AAMD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,EACvB,yBAAyB,CAAC,EAAE,MAAM,GACjC,MAAM,GAAG,SAAS,CAEpB;AAED,KAAK,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC;AAEhF,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,KAAK,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAiBD,wBAAsB,iCAAiC,CAAC,KAAK,EAAE;IAC7D,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAyCtC;AA2BD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,CAoWjB;AAED,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,QAAQ,EAAE,EACrB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA4M1C;AAUD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACnF,QAAQ,EAAE,CAqBZ;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACnF,OAAO,CAAC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAY1C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACnF;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAqF1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-converter.d.ts","sourceRoot":"","sources":["../../src/lib/session-converter.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAsBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAqDnE;AAkBD,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,EAAE,CAqD5D;AAsDD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,YAAY,EAAE,EACtB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,iBAAiB,CAAC,CA0D5B;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,iBAAiB,CAAC,CAoC5B;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAiBnE"}
1
+ {"version":3,"file":"session-converter.d.ts","sourceRoot":"","sources":["../../src/lib/session-converter.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAsBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAqDnE;AAkBD,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,EAAE,CAqD5D;AAsDD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,YAAY,EAAE,EACtB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,iBAAiB,CAAC,CAkE5B;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,iBAAiB,CAAC,CAoC5B;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAiBnE"}
package/dist/mcp/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@hasna/testers",
55
- version: "0.0.35",
55
+ version: "0.0.36",
56
56
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
57
57
  type: "module",
58
58
  main: "dist/index.js",
@@ -16600,6 +16600,10 @@ function loadConfig() {
16600
16600
  if (envApiKey) {
16601
16601
  config.anthropicApiKey = envApiKey;
16602
16602
  }
16603
+ const envSelfHeal = process.env["TESTERS_SELF_HEAL"];
16604
+ if (envSelfHeal !== undefined) {
16605
+ config.selfHeal = ["1", "true", "yes", "on"].includes(envSelfHeal.toLowerCase());
16606
+ }
16603
16607
  return config;
16604
16608
  }
16605
16609
  function resolveModel(nameOrId) {
@@ -16642,12 +16646,11 @@ Original selector that failed: "${request.failedSelector}"
16642
16646
  Please identify the correct selector from the screenshot.`;
16643
16647
  let rawResponse = "";
16644
16648
  try {
16645
- if (provider === "openai" || provider === "google") {
16646
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
16647
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
16649
+ if (provider !== "anthropic") {
16650
+ const compat = createOpenAICompatibleConfig(provider);
16648
16651
  const resp = await callOpenAICompatible({
16649
- baseUrl,
16650
- apiKey,
16652
+ baseUrl: compat.baseUrl,
16653
+ apiKey: compat.apiKey,
16651
16654
  model,
16652
16655
  system: HEAL_SYSTEM,
16653
16656
  messages: [{ role: "user", content: userMessage }],
@@ -16741,9 +16744,11 @@ var init_healer = __esm(() => {
16741
16744
  var exports_ai_client = {};
16742
16745
  __export(exports_ai_client, {
16743
16746
  runAgentLoop: () => runAgentLoop,
16747
+ resolveProviderApiKeyForModel: () => resolveProviderApiKeyForModel,
16744
16748
  resolveModel: () => resolveModel2,
16745
16749
  executeTool: () => executeTool,
16746
16750
  detectProvider: () => detectProvider,
16751
+ createOpenAICompatibleConfig: () => createOpenAICompatibleConfig,
16747
16752
  createClientForModel: () => createClientForModel,
16748
16753
  createClient: () => createClient,
16749
16754
  callOpenAICompatible: () => callOpenAICompatible,
@@ -17566,10 +17571,17 @@ function detectProvider(model) {
17566
17571
  return "openai";
17567
17572
  if (model.startsWith("gemini-"))
17568
17573
  return "google";
17574
+ if (model.startsWith("glm-") || model.startsWith("zai/") || model.startsWith("zai-"))
17575
+ return "zai";
17569
17576
  if (model.startsWith("llama-") || model.startsWith("qwen-") || model.includes("cerebras"))
17570
17577
  return "cerebras";
17571
17578
  return "anthropic";
17572
17579
  }
17580
+ function resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
17581
+ if (explicitApiKey)
17582
+ return explicitApiKey;
17583
+ return detectProvider(model) === "anthropic" ? configuredAnthropicApiKey : undefined;
17584
+ }
17573
17585
  function createClient(apiKey) {
17574
17586
  const key = apiKey ?? process.env["ANTHROPIC_API_KEY"];
17575
17587
  if (!key) {
@@ -17647,26 +17659,34 @@ async function callOpenAICompatible(options) {
17647
17659
  const usage = { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0 };
17648
17660
  return { content, stop_reason: stopReason, usage };
17649
17661
  }
17650
- function createClientForModel(model, apiKey) {
17651
- const provider = detectProvider(model);
17662
+ function createOpenAICompatibleConfig(provider, apiKey) {
17652
17663
  if (provider === "openai") {
17653
- const key = apiKey ?? process.env["OPENAI_API_KEY"];
17654
- if (!key)
17664
+ const key2 = apiKey ?? process.env["OPENAI_API_KEY"];
17665
+ if (!key2)
17655
17666
  throw new AIClientError("No OpenAI API key. Set OPENAI_API_KEY or pass it explicitly.");
17656
- return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key };
17667
+ return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key2 };
17657
17668
  }
17658
17669
  if (provider === "google") {
17659
- const key = apiKey ?? process.env["GOOGLE_API_KEY"];
17660
- if (!key)
17670
+ const key2 = apiKey ?? process.env["GOOGLE_API_KEY"];
17671
+ if (!key2)
17661
17672
  throw new AIClientError("No Google API key. Set GOOGLE_API_KEY or pass it explicitly.");
17662
- return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key };
17673
+ return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key2 };
17663
17674
  }
17664
17675
  if (provider === "cerebras") {
17665
- const key = apiKey ?? process.env["CEREBRAS_API_KEY"];
17666
- if (!key)
17676
+ const key2 = apiKey ?? process.env["CEREBRAS_API_KEY"];
17677
+ if (!key2)
17667
17678
  throw new AIClientError("No Cerebras API key. Set CEREBRAS_API_KEY or pass it explicitly.");
17668
- return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key };
17679
+ return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key2 };
17669
17680
  }
17681
+ const key = apiKey ?? process.env["ZAI_API_KEY"];
17682
+ if (!key)
17683
+ throw new AIClientError("No Z.AI API key. Set ZAI_API_KEY or pass it explicitly.");
17684
+ return { provider: "zai", baseUrl: "https://api.z.ai/api/paas/v4", apiKey: key };
17685
+ }
17686
+ function createClientForModel(model, apiKey) {
17687
+ const provider = detectProvider(model);
17688
+ if (provider !== "anthropic")
17689
+ return createOpenAICompatibleConfig(provider, apiKey);
17670
17690
  return createClient(apiKey);
17671
17691
  }
17672
17692
  var activeHARs, activeCoverage, BROWSER_TOOLS;
@@ -18243,22 +18263,22 @@ function resolveJudgeModel(config) {
18243
18263
  apiKey = process.env["GOOGLE_API_KEY"];
18244
18264
  else if (provider === "cerebras")
18245
18265
  apiKey = process.env["CEREBRAS_API_KEY"];
18266
+ else if (provider === "zai")
18267
+ apiKey = process.env["ZAI_API_KEY"];
18246
18268
  }
18247
18269
  if (!apiKey) {
18248
- apiKey = process.env["ANTHROPIC_API_KEY"] ?? process.env["CEREBRAS_API_KEY"] ?? process.env["OPENAI_API_KEY"] ?? process.env["GOOGLE_API_KEY"] ?? globalConfig.anthropicApiKey;
18249
- if (!apiKey)
18250
- throw new AIClientError("No API key found for judge. Set ANTHROPIC_API_KEY, CEREBRAS_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY.");
18270
+ throw new AIClientError(`No API key found for ${provider} judge provider.`);
18251
18271
  }
18252
18272
  return { model, provider, apiKey };
18253
18273
  }
18254
18274
  async function callJudge(prompt, config) {
18255
18275
  const { model, provider, apiKey } = resolveJudgeModel(config);
18256
18276
  const threshold = 0.7;
18257
- if (provider === "openai" || provider === "google" || provider === "cerebras") {
18258
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : provider === "cerebras" ? "https://api.cerebras.ai/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
18277
+ if (provider !== "anthropic") {
18278
+ const compat = createOpenAICompatibleConfig(provider, apiKey);
18259
18279
  const resp2 = await callOpenAICompatible({
18260
- baseUrl,
18261
- apiKey,
18280
+ baseUrl: compat.baseUrl,
18281
+ apiKey: compat.apiKey,
18262
18282
  model,
18263
18283
  system: LLM_SYSTEM,
18264
18284
  messages: [{ role: "user", content: prompt }],
@@ -21159,6 +21179,7 @@ __export(exports_runner, {
21159
21179
  runByFilter: () => runByFilter,
21160
21180
  runBatch: () => runBatch,
21161
21181
  resolveScenariosForRun: () => resolveScenariosForRun,
21182
+ resolveAgentApiKeyForModel: () => resolveAgentApiKeyForModel,
21162
21183
  onRunEvent: () => onRunEvent,
21163
21184
  applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
21164
21185
  });
@@ -21172,6 +21193,9 @@ function emit(event) {
21172
21193
  if (eventHandler)
21173
21194
  eventHandler(event);
21174
21195
  }
21196
+ function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
21197
+ return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
21198
+ }
21175
21199
  function assertionDescription(result) {
21176
21200
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
21177
21201
  }
@@ -21280,7 +21304,7 @@ async function runSingleScenario(scenario, runId, options) {
21280
21304
  });
21281
21305
  }
21282
21306
  }
21283
- const client = createClientForModel(model, effectiveOptions.apiKey ?? config.anthropicApiKey);
21307
+ const client = createClientForModel(model, resolveAgentApiKeyForModel(model, effectiveOptions.apiKey, config.anthropicApiKey));
21284
21308
  const screenshotter = new Screenshotter({
21285
21309
  baseDir: effectiveOptions.screenshotDir ?? config.screenshots.dir
21286
21310
  });
@@ -85705,12 +85729,28 @@ Rules:
85705
85729
  ];
85706
85730
  const messages = [{ role: "user", content: contentParts }];
85707
85731
  try {
85708
- const response = await anthropicClient.messages.create({
85709
- model,
85710
- max_tokens: 2048,
85711
- messages
85712
- });
85713
- const text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85732
+ let text2;
85733
+ const provider = detectProvider(model);
85734
+ if (provider !== "anthropic") {
85735
+ const compat2 = client;
85736
+ const response = await callOpenAICompatible({
85737
+ baseUrl: compat2.baseUrl,
85738
+ apiKey: compat2.apiKey,
85739
+ model,
85740
+ system: "You are a QA engineer.",
85741
+ messages: [{ role: "user", content: prompt }],
85742
+ tools: [],
85743
+ maxTokens: 2048
85744
+ });
85745
+ text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85746
+ } else {
85747
+ const response = await anthropicClient.messages.create({
85748
+ model,
85749
+ max_tokens: 2048,
85750
+ messages
85751
+ });
85752
+ text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85753
+ }
85714
85754
  const match = text2.match(/\[[\s\S]*\]/);
85715
85755
  if (!match)
85716
85756
  return [];
@@ -85738,7 +85778,7 @@ async function crawlAndGenerate(options) {
85738
85778
  } = options;
85739
85779
  const config2 = loadConfig();
85740
85780
  const model = resolveModel2(options.model ?? config2.defaultModel ?? "thorough");
85741
- const client = createClient(options.apiKey ?? config2.anthropicApiKey);
85781
+ const client = createClientForModel(model, resolveProviderApiKeyForModel(model, options.apiKey, config2.anthropicApiKey));
85742
85782
  const rootOrigin = new URL(url2).origin;
85743
85783
  const visited = new Set;
85744
85784
  const queue = [url2];
@@ -85818,7 +85858,6 @@ var init_crawl_and_generate = __esm(() => {
85818
85858
  init_scenarios();
85819
85859
  init_ai_client();
85820
85860
  init_config2();
85821
- init_ai_client();
85822
85861
  DEFAULT_SKIP_PATTERNS = [
85823
85862
  "/logout",
85824
85863
  "/sign-out",
@@ -15319,6 +15319,10 @@ function loadConfig() {
15319
15319
  if (envApiKey) {
15320
15320
  config.anthropicApiKey = envApiKey;
15321
15321
  }
15322
+ const envSelfHeal = process.env["TESTERS_SELF_HEAL"];
15323
+ if (envSelfHeal !== undefined) {
15324
+ config.selfHeal = ["1", "true", "yes", "on"].includes(envSelfHeal.toLowerCase());
15325
+ }
15322
15326
  return config;
15323
15327
  }
15324
15328
  var CONFIG_DIR3, CONFIG_PATH2;
@@ -15355,12 +15359,11 @@ Original selector that failed: "${request.failedSelector}"
15355
15359
  Please identify the correct selector from the screenshot.`;
15356
15360
  let rawResponse = "";
15357
15361
  try {
15358
- if (provider === "openai" || provider === "google") {
15359
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
15360
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
15362
+ if (provider !== "anthropic") {
15363
+ const compat = createOpenAICompatibleConfig(provider);
15361
15364
  const resp = await callOpenAICompatible({
15362
- baseUrl,
15363
- apiKey,
15365
+ baseUrl: compat.baseUrl,
15366
+ apiKey: compat.apiKey,
15364
15367
  model,
15365
15368
  system: HEAL_SYSTEM,
15366
15369
  messages: [{ role: "user", content: userMessage }],
@@ -16267,10 +16270,17 @@ function detectProvider(model) {
16267
16270
  return "openai";
16268
16271
  if (model.startsWith("gemini-"))
16269
16272
  return "google";
16273
+ if (model.startsWith("glm-") || model.startsWith("zai/") || model.startsWith("zai-"))
16274
+ return "zai";
16270
16275
  if (model.startsWith("llama-") || model.startsWith("qwen-") || model.includes("cerebras"))
16271
16276
  return "cerebras";
16272
16277
  return "anthropic";
16273
16278
  }
16279
+ function resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
16280
+ if (explicitApiKey)
16281
+ return explicitApiKey;
16282
+ return detectProvider(model) === "anthropic" ? configuredAnthropicApiKey : undefined;
16283
+ }
16274
16284
  function createClient(apiKey) {
16275
16285
  const key = apiKey ?? process.env["ANTHROPIC_API_KEY"];
16276
16286
  if (!key) {
@@ -16348,26 +16358,34 @@ async function callOpenAICompatible(options) {
16348
16358
  const usage = { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0 };
16349
16359
  return { content, stop_reason: stopReason, usage };
16350
16360
  }
16351
- function createClientForModel(model, apiKey) {
16352
- const provider = detectProvider(model);
16361
+ function createOpenAICompatibleConfig(provider, apiKey) {
16353
16362
  if (provider === "openai") {
16354
- const key = apiKey ?? process.env["OPENAI_API_KEY"];
16355
- if (!key)
16363
+ const key2 = apiKey ?? process.env["OPENAI_API_KEY"];
16364
+ if (!key2)
16356
16365
  throw new AIClientError("No OpenAI API key. Set OPENAI_API_KEY or pass it explicitly.");
16357
- return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key };
16366
+ return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key2 };
16358
16367
  }
16359
16368
  if (provider === "google") {
16360
- const key = apiKey ?? process.env["GOOGLE_API_KEY"];
16361
- if (!key)
16369
+ const key2 = apiKey ?? process.env["GOOGLE_API_KEY"];
16370
+ if (!key2)
16362
16371
  throw new AIClientError("No Google API key. Set GOOGLE_API_KEY or pass it explicitly.");
16363
- return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key };
16372
+ return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key2 };
16364
16373
  }
16365
16374
  if (provider === "cerebras") {
16366
- const key = apiKey ?? process.env["CEREBRAS_API_KEY"];
16367
- if (!key)
16375
+ const key2 = apiKey ?? process.env["CEREBRAS_API_KEY"];
16376
+ if (!key2)
16368
16377
  throw new AIClientError("No Cerebras API key. Set CEREBRAS_API_KEY or pass it explicitly.");
16369
- return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key };
16378
+ return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key2 };
16370
16379
  }
16380
+ const key = apiKey ?? process.env["ZAI_API_KEY"];
16381
+ if (!key)
16382
+ throw new AIClientError("No Z.AI API key. Set ZAI_API_KEY or pass it explicitly.");
16383
+ return { provider: "zai", baseUrl: "https://api.z.ai/api/paas/v4", apiKey: key };
16384
+ }
16385
+ function createClientForModel(model, apiKey) {
16386
+ const provider = detectProvider(model);
16387
+ if (provider !== "anthropic")
16388
+ return createOpenAICompatibleConfig(provider, apiKey);
16371
16389
  return createClient(apiKey);
16372
16390
  }
16373
16391
  var activeHARs, activeCoverage, BROWSER_TOOLS;
@@ -46892,7 +46910,7 @@ import { join as join14 } from "path";
46892
46910
  // package.json
46893
46911
  var package_default = {
46894
46912
  name: "@hasna/testers",
46895
- version: "0.0.35",
46913
+ version: "0.0.36",
46896
46914
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
46897
46915
  type: "module",
46898
46916
  main: "dist/index.js",
@@ -47471,11 +47489,11 @@ function resolveJudgeModel(config) {
47471
47489
  apiKey = process.env["GOOGLE_API_KEY"];
47472
47490
  else if (provider === "cerebras")
47473
47491
  apiKey = process.env["CEREBRAS_API_KEY"];
47492
+ else if (provider === "zai")
47493
+ apiKey = process.env["ZAI_API_KEY"];
47474
47494
  }
47475
47495
  if (!apiKey) {
47476
- apiKey = process.env["ANTHROPIC_API_KEY"] ?? process.env["CEREBRAS_API_KEY"] ?? process.env["OPENAI_API_KEY"] ?? process.env["GOOGLE_API_KEY"] ?? globalConfig.anthropicApiKey;
47477
- if (!apiKey)
47478
- throw new AIClientError("No API key found for judge. Set ANTHROPIC_API_KEY, CEREBRAS_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY.");
47496
+ throw new AIClientError(`No API key found for ${provider} judge provider.`);
47479
47497
  }
47480
47498
  return { model, provider, apiKey };
47481
47499
  }
@@ -47490,11 +47508,11 @@ reason: 1-2 sentences max`;
47490
47508
  async function callJudge(prompt, config) {
47491
47509
  const { model, provider, apiKey } = resolveJudgeModel(config);
47492
47510
  const threshold = 0.7;
47493
- if (provider === "openai" || provider === "google" || provider === "cerebras") {
47494
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : provider === "cerebras" ? "https://api.cerebras.ai/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
47511
+ if (provider !== "anthropic") {
47512
+ const compat = createOpenAICompatibleConfig(provider, apiKey);
47495
47513
  const resp2 = await callOpenAICompatible({
47496
- baseUrl,
47497
- apiKey,
47514
+ baseUrl: compat.baseUrl,
47515
+ apiKey: compat.apiKey,
47498
47516
  model,
47499
47517
  system: LLM_SYSTEM,
47500
47518
  messages: [{ role: "user", content: prompt }],
@@ -49382,6 +49400,9 @@ function emit(event) {
49382
49400
  if (eventHandler)
49383
49401
  eventHandler(event);
49384
49402
  }
49403
+ function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
49404
+ return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
49405
+ }
49385
49406
  function assertionDescription(result) {
49386
49407
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
49387
49408
  }
@@ -49490,7 +49511,7 @@ async function runSingleScenario(scenario, runId, options) {
49490
49511
  });
49491
49512
  }
49492
49513
  }
49493
- const client = createClientForModel(model, effectiveOptions.apiKey ?? config.anthropicApiKey);
49514
+ const client = createClientForModel(model, resolveAgentApiKeyForModel(model, effectiveOptions.apiKey, config.anthropicApiKey));
49494
49515
  const screenshotter = new Screenshotter({
49495
49516
  baseDir: effectiveOptions.screenshotDir ?? config.screenshots.dir
49496
49517
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/testers",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "description": "AI-powered QA testing CLI — spawns cheap AI agents to test web apps with headless browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",