@testdriverai/mcp 7.11.180-test → 7.11.181-test

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.
@@ -6,8 +6,8 @@ const require = createRequire(import.meta.url);
6
6
  const { createSDK, withRetry } = require("./sdk.js");
7
7
 
8
8
  /**
9
- * A team's OpenRouter key can be revoked, run out of credit, or never be
10
- * configured. The API reports that as a 400 carrying an OPENROUTER_* code.
9
+ * A team's Google (Gemini) key can be revoked, run out of quota, or never be
10
+ * configured. The API reports that as a 400 carrying a GOOGLE_* code.
11
11
  * Two things have to hold for the user to ever see it: the request layer must
12
12
  * not retry it into a two-minute stall, and it must arrive as a real error with
13
13
  * `isConfigError` set — that flag is what stops find()/findAll() from folding it
@@ -21,12 +21,12 @@ const axiosError = (status, data) =>
21
21
 
22
22
  const KEY_ERROR_BODY = {
23
23
  error:
24
- "Your team's OpenRouter API key has no credits remaining — HTTP 402. Add credits at https://openrouter.ai/credits.",
25
- code: "OPENROUTER_KEY_ERROR",
26
- details: { openrouterStatus: 402, source: "testdriver-locate" },
24
+ "Your team's Google API key has no quota remaining — HTTP 429. Check your quota at https://aistudio.google.com/apikey.",
25
+ code: "GOOGLE_KEY_ERROR",
26
+ details: { geminiStatus: 429, source: "testdriver-locate" },
27
27
  };
28
28
 
29
- describe("OpenRouter key errors are not retried", () => {
29
+ describe("Google key errors are not retried", () => {
30
30
  it("fails a rejected key on the first attempt", async () => {
31
31
  let attempts = 0;
32
32
  await expect(
@@ -44,8 +44,8 @@ describe("OpenRouter key errors are not retried", () => {
44
44
  withRetry(async () => {
45
45
  attempts++;
46
46
  throw axiosError(400, {
47
- error: "OpenRouter API key is required for self-hosted plans.",
48
- code: "OPENROUTER_KEY_REQUIRED",
47
+ error: "Google API key is required for self-hosted plans.",
48
+ code: "GOOGLE_KEY_REQUIRED",
49
49
  });
50
50
  }),
51
51
  ).rejects.toThrow();
@@ -81,7 +81,7 @@ describe("OpenRouter key errors are not retried", () => {
81
81
  });
82
82
  });
83
83
 
84
- describe("OpenRouter key errors reach the caller", () => {
84
+ describe("Google key errors reach the caller", () => {
85
85
  /** Serve one 400 with the given body, then hand back its origin. */
86
86
  const serve = async (body) => {
87
87
  const server = http.createServer((req, res) => {
@@ -112,7 +112,7 @@ describe("OpenRouter key errors reach the caller", () => {
112
112
 
113
113
  expect(error).toBeTruthy();
114
114
  expect(error.isConfigError).toBe(true);
115
- expect(error.code).toBe("OPENROUTER_KEY_ERROR");
115
+ expect(error.code).toBe("GOOGLE_KEY_ERROR");
116
116
  expect(error.message).toBe(KEY_ERROR_BODY.error);
117
117
  expect(error.details).toEqual(KEY_ERROR_BODY.details);
118
118
 
package/agent/lib/sdk.js CHANGED
@@ -36,6 +36,9 @@ const DEFAULT_RETRY_CONFIG = {
36
36
  * retrying only delays the message the user needs to read.
37
37
  */
38
38
  const CONFIG_ERROR_CODES = [
39
+ "GOOGLE_KEY_ERROR",
40
+ "GOOGLE_KEY_REQUIRED",
41
+ // Kept for backward compatibility with older API deployments.
39
42
  "OPENROUTER_KEY_ERROR",
40
43
  "OPENROUTER_KEY_REQUIRED",
41
44
  ];
@@ -58,7 +61,7 @@ function apiErrorCode(error) {
58
61
  * @returns {boolean} Whether the request should be retried
59
62
  */
60
63
  function isRetryableError(error, config = DEFAULT_RETRY_CONFIG) {
61
- // A rejected OpenRouter key (or a missing one) is not going to start working
64
+ // A rejected Google key (or a missing one) is not going to start working
62
65
  // on attempt two — surface it now instead of after ten backoffs.
63
66
  if (CONFIG_ERROR_CODES.includes(apiErrorCode(error))) {
64
67
  return false;
@@ -607,7 +610,7 @@ const createSDK = (emitter, config, sessionInstance) => {
607
610
  const status = error.response?.status;
608
611
 
609
612
  // Configuration errors (400 + a known code) — the API rejected the call
610
- // for a reason the user can fix, most often an OpenRouter key that was
613
+ // for a reason the user can fix, most often a Google key that was
611
614
  // revoked, ran out of credit, or was never configured. These used to
612
615
  // arrive as a bare "Request failed with status code 400" and get folded
613
616
  // into "element not found", so the real cause never reached the user.
@@ -46,6 +46,10 @@ Run test sandboxes on your AWS infrastructure while using TestDriver's hosted da
46
46
  - **Your AI keys** — control costs with your own OpenAI, Anthropic, or other provider
47
47
  - **Custom AMIs** — install specific software, configure networking
48
48
 
49
+ <Note>
50
+ **Bring your own Gemini API key.** TestDriver uses Google Gemini for vision and reasoning. When supplying your own Gemini key, it must be a [Gemini Enterprise Agent Platform express mode API key](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/start/api-keys?usertype=expressmode) — standard Google AI Studio (Generative Language API) keys are not supported for self-hosted deployments.
51
+ </Note>
52
+
49
53
  <Card
50
54
  title="AWS Setup Guide"
51
55
  icon="aws"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testdriverai/mcp",
3
- "version": "7.11.180-test",
3
+ "version": "7.11.181-test",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "sdk.js",
6
6
  "types": "sdk.d.ts",
package/sdk.js CHANGED
@@ -623,7 +623,7 @@ class Element {
623
623
  this.sdk.emitter.emit(events.log.log, notFoundMessage);
624
624
  }
625
625
  } catch (error) {
626
- // A rejected or missing OpenRouter key breaks every find the same way.
626
+ // A rejected or missing Google key breaks every find the same way.
627
627
  // Reporting it as "element not found" hides the one thing the user needs
628
628
  // to know, so it escapes instead of being folded into the not-found path.
629
629
  if (error.isConfigError) {
@@ -2671,7 +2671,7 @@ CAPTCHA_SOLVER_EOF`,
2671
2671
  } catch (error) {
2672
2672
  const duration = Date.now() - startTime;
2673
2673
 
2674
- // A rejected or missing OpenRouter key isn't "zero elements matched" —
2674
+ // A rejected or missing Google key isn't "zero elements matched" —
2675
2675
  // returning [] here would hide the only thing the user can act on.
2676
2676
  if (error.isConfigError) {
2677
2677
  this._lastPromiseSettled = true;