testdriverai 7.8.0-test.5 → 7.8.0-test.50

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/agent/index.js +6 -5
  3. package/agent/lib/commands.js +3 -2
  4. package/agent/lib/http.js +144 -0
  5. package/agent/lib/sandbox.js +492 -203
  6. package/agent/lib/sdk.js +4 -2
  7. package/agent/lib/system.js +25 -65
  8. package/ai/skills/testdriver-cache/SKILL.md +221 -0
  9. package/ai/skills/testdriver-errors/SKILL.md +246 -0
  10. package/ai/skills/testdriver-events/SKILL.md +356 -0
  11. package/ai/skills/testdriver-mcp/SKILL.md +7 -0
  12. package/ai/skills/testdriver-provision/SKILL.md +331 -0
  13. package/ai/skills/testdriver-redraw/SKILL.md +214 -0
  14. package/ai/skills/testdriver-running-tests/SKILL.md +1 -1
  15. package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
  16. package/docs/_data/examples-manifest.json +46 -46
  17. package/docs/changelog.mdx +155 -3
  18. package/docs/docs.json +44 -37
  19. package/docs/images/content/vscode/v7-chat.png +0 -0
  20. package/docs/images/content/vscode/v7-choose-agent.png +0 -0
  21. package/docs/images/content/vscode/v7-full.png +0 -0
  22. package/docs/images/content/vscode/v7-onboarding.png +0 -0
  23. package/docs/v7/cache.mdx +223 -0
  24. package/docs/v7/copilot/auto-healing.mdx +265 -0
  25. package/docs/v7/copilot/creating-tests.mdx +156 -0
  26. package/docs/v7/copilot/github.mdx +143 -0
  27. package/docs/v7/copilot/running-tests.mdx +149 -0
  28. package/docs/v7/copilot/setup.mdx +143 -0
  29. package/docs/v7/enterprise.mdx +3 -110
  30. package/docs/v7/errors.mdx +248 -0
  31. package/docs/v7/events.mdx +358 -0
  32. package/docs/v7/examples/ai.mdx +1 -1
  33. package/docs/v7/examples/assert.mdx +1 -1
  34. package/docs/v7/examples/captcha-api.mdx +1 -1
  35. package/docs/v7/examples/chrome-extension.mdx +1 -1
  36. package/docs/v7/examples/drag-and-drop.mdx +1 -1
  37. package/docs/v7/examples/element-not-found.mdx +1 -1
  38. package/docs/v7/examples/exec-output.mdx +85 -0
  39. package/docs/v7/examples/exec-pwsh.mdx +83 -0
  40. package/docs/v7/examples/focus-window.mdx +62 -0
  41. package/docs/v7/examples/hover-image.mdx +1 -1
  42. package/docs/v7/examples/hover-text.mdx +1 -1
  43. package/docs/v7/examples/installer.mdx +1 -1
  44. package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
  45. package/docs/v7/examples/match-image.mdx +1 -1
  46. package/docs/v7/examples/press-keys.mdx +1 -1
  47. package/docs/v7/examples/scroll-keyboard.mdx +1 -1
  48. package/docs/v7/examples/scroll-until-image.mdx +1 -1
  49. package/docs/v7/examples/scroll-until-text.mdx +1 -1
  50. package/docs/v7/examples/scroll.mdx +1 -1
  51. package/docs/v7/examples/type.mdx +1 -1
  52. package/docs/v7/examples/windows-installer.mdx +1 -1
  53. package/docs/v7/{cloud.mdx → hosted.mdx} +43 -5
  54. package/docs/v7/mcp.mdx +9 -0
  55. package/docs/v7/provision.mdx +333 -0
  56. package/docs/v7/quickstart.mdx +30 -2
  57. package/docs/v7/redraw.mdx +216 -0
  58. package/docs/v7/running-tests.mdx +1 -1
  59. package/docs/v7/screenshots.mdx +186 -0
  60. package/docs/v7/self-hosted.mdx +127 -44
  61. package/interfaces/logger.js +0 -12
  62. package/interfaces/vitest-plugin.mjs +53 -43
  63. package/lib/core/Dashcam.js +30 -23
  64. package/lib/environments.json +18 -0
  65. package/lib/github-comment.mjs +58 -40
  66. package/lib/resolve-channel.js +4 -3
  67. package/lib/sentry.js +5 -0
  68. package/lib/vitest/hooks.mjs +3 -3
  69. package/{examples → manual}/drag-and-drop.test.mjs +1 -1
  70. package/mcp-server/dist/server.mjs +4 -0
  71. package/mcp-server/src/server.ts +5 -0
  72. package/package.json +3 -3
  73. package/sdk.js +3 -3
  74. package/setup/aws/install-dev-runner.sh +79 -0
  75. package/setup/aws/spawn-runner.sh +134 -0
  76. package/vitest.config.mjs +22 -34
  77. package/vitest.runner.config.mjs +33 -0
  78. /package/{examples → manual}/flake-diffthreshold-001.test.mjs +0 -0
  79. /package/{examples → manual}/flake-diffthreshold-01.test.mjs +0 -0
  80. /package/{examples → manual}/flake-diffthreshold-05.test.mjs +0 -0
  81. /package/{examples → manual}/flake-noredraw-cache.test.mjs +0 -0
  82. /package/{examples → manual}/flake-noredraw-nocache.test.mjs +0 -0
  83. /package/{examples → manual}/flake-redraw-cache.test.mjs +0 -0
  84. /package/{examples → manual}/flake-redraw-nocache.test.mjs +0 -0
  85. /package/{examples → manual}/flake-rocket-match.test.mjs +0 -0
  86. /package/{examples → manual}/flake-shared.mjs +0 -0
  87. /package/{examples → manual}/no-provision.test.mjs +0 -0
  88. /package/{examples → manual}/scroll-until-text.test.mjs +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 7.8.0-test.7 (2026-03-13)
2
+
3
+ 🔧 Maintenance
4
+
5
+ - Fix version bump syntax in release workflow [f3ac61dc]
6
+
7
+ ## 7.8.0-test.6 (2026-03-13)
8
+
9
+ 🔧 Maintenance
10
+
11
+ - Fix changelog generation in release workflow (04a789ec)
12
+
1
13
  ## 7.8.0-test.5 (2026-03-13)
2
14
 
3
15
  🔧 Maintenance
package/agent/index.js CHANGED
@@ -1941,18 +1941,19 @@ ${regression}
1941
1941
  // Allow explicit override via env (e.g. VITE_DOMAIN from .env)
1942
1942
  if (process.env.VITE_DOMAIN) return process.env.VITE_DOMAIN;
1943
1943
 
1944
+ const environments = require("../lib/environments.json");
1944
1945
  const mapping = {
1945
- "https://api.testdriver.ai": "https://console.testdriver.ai",
1946
- "https://v6.testdriver.ai": "https://console.testdriver.ai",
1947
- "https://api-canary.testdriver.ai": "https://console-canary.testdriver.ai",
1948
- "https://api-test.testdriver.ai": "https://console-test.testdriver.ai",
1946
+ "https://v6.testdriver.ai": environments.stable.consoleUrl,
1949
1947
  };
1948
+ for (const env of Object.values(environments)) {
1949
+ mapping[env.apiRoot] = env.consoleUrl;
1950
+ }
1950
1951
  if (mapping[apiRoot]) return mapping[apiRoot];
1951
1952
  // Local dev: API on localhost:1337 -> Web on localhost:3001
1952
1953
  if (apiRoot.includes("localhost:1337") || apiRoot.includes("127.0.0.1:1337")) {
1953
1954
  return "http://localhost:3001";
1954
1955
  }
1955
- return "https://console.testdriver.ai";
1956
+ return environments.stable.consoleUrl;
1956
1957
  }
1957
1958
 
1958
1959
  // Write session file for IDE preview (VSCode extension watches for these)
@@ -580,11 +580,12 @@ const createCommands = (
580
580
  } else if (action === "mouseDown") {
581
581
  await sandbox.send({ type: "mousePress", button: "left", x, y, ...elementData });
582
582
  } else if (action === "mouseUp") {
583
+ // Move first to create drag motion, then release
584
+ // (pyautogui.mouseUp with x/y teleports instead of dragging)
585
+ await sandbox.send({ type: "moveMouse", x, y, ...elementData });
583
586
  await sandbox.send({
584
587
  type: "mouseRelease",
585
588
  button: "left",
586
- x,
587
- y,
588
589
  ...elementData
589
590
  });
590
591
  }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Shared HTTP client for the TestDriver SDK.
3
+ *
4
+ * All SDK HTTP traffic should go through these helpers so that
5
+ * User-Agent, timeouts, Sentry tracing headers, and response
6
+ * parsing are handled in one place.
7
+ *
8
+ * Uses axios under the hood — the same library the rest of the SDK
9
+ * already depends on.
10
+ */
11
+
12
+ const axios = require("axios");
13
+ const crypto = require("crypto");
14
+ const { version } = require("../../package.json");
15
+
16
+ const USER_AGENT = `TestDriverSDK/${version} (Node.js ${process.version})`;
17
+
18
+ /**
19
+ * Generate Sentry distributed-tracing headers from a session ID.
20
+ * Both sandbox.js and sdk.js duplicated this — it now lives here.
21
+ *
22
+ * @param {string} sessionId
23
+ * @returns {object} Headers object (empty if no sessionId)
24
+ */
25
+ function getSentryTraceHeaders(sessionId) {
26
+ if (!sessionId) return {};
27
+ const traceId = crypto.createHash("md5").update(sessionId).digest("hex");
28
+ const spanId = crypto.randomBytes(8).toString("hex");
29
+ return {
30
+ "sentry-trace": traceId + "-" + spanId + "-1",
31
+ baggage:
32
+ "sentry-trace_id=" +
33
+ traceId +
34
+ ",sentry-sample_rate=1.0,sentry-sampled=true",
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Build common request headers.
40
+ * @param {object} [extra] - Additional headers to merge
41
+ * @returns {object}
42
+ */
43
+ function baseHeaders(extra) {
44
+ return {
45
+ "User-Agent": USER_AGENT,
46
+ ...extra,
47
+ };
48
+ }
49
+
50
+ /**
51
+ * POST JSON to `url` and return the parsed response body.
52
+ *
53
+ * @param {string} url - Absolute URL
54
+ * @param {object} [data] - JSON body
55
+ * @param {object} [opts] - Extra axios config (headers, timeout, …)
56
+ * @returns {Promise<object>} Parsed response data
57
+ */
58
+ async function httpPost(url, data, opts = {}) {
59
+ const { headers: extraHeaders, ...rest } = opts;
60
+ const res = await axios({
61
+ method: "post",
62
+ url,
63
+ headers: baseHeaders({
64
+ "Content-Type": "application/json",
65
+ ...extraHeaders,
66
+ }),
67
+ data,
68
+ timeout: opts.timeout || 30000,
69
+ ...rest,
70
+ });
71
+ return res.data;
72
+ }
73
+
74
+ /**
75
+ * GET `url` and return the parsed response body.
76
+ *
77
+ * @param {string} url - Absolute URL
78
+ * @param {object} [opts] - Extra axios config
79
+ * @returns {Promise<object>} Parsed response data
80
+ */
81
+ async function httpGet(url, opts = {}) {
82
+ const { headers: extraHeaders, ...rest } = opts;
83
+ const res = await axios({
84
+ method: "get",
85
+ url,
86
+ headers: baseHeaders(extraHeaders),
87
+ timeout: opts.timeout || 30000,
88
+ ...rest,
89
+ });
90
+ return res.data;
91
+ }
92
+
93
+ /**
94
+ * PUT data to `url` (e.g. S3 presigned upload).
95
+ *
96
+ * @param {string} url - Absolute URL
97
+ * @param {Buffer|string} data - Request body
98
+ * @param {object} [opts] - Extra axios config (headers, timeout, …)
99
+ * @returns {Promise<object>} Parsed response data (or empty object for 2xx with no body)
100
+ */
101
+ async function httpPut(url, data, opts = {}) {
102
+ const { headers: extraHeaders, ...rest } = opts;
103
+ const res = await axios({
104
+ method: "put",
105
+ url,
106
+ headers: baseHeaders(extraHeaders),
107
+ data,
108
+ timeout: opts.timeout || 30000,
109
+ maxBodyLength: Infinity,
110
+ maxContentLength: Infinity,
111
+ ...rest,
112
+ });
113
+ return res.data;
114
+ }
115
+
116
+ /**
117
+ * Download a URL as a Buffer (e.g. screenshot from S3).
118
+ *
119
+ * @param {string} url - Absolute URL
120
+ * @param {object} [opts] - Extra axios config
121
+ * @returns {Promise<Buffer>}
122
+ */
123
+ async function downloadBuffer(url, opts = {}) {
124
+ const { headers: extraHeaders, ...rest } = opts;
125
+ const res = await axios({
126
+ method: "get",
127
+ url,
128
+ headers: baseHeaders(extraHeaders),
129
+ responseType: "arraybuffer",
130
+ timeout: opts.timeout || 60000,
131
+ ...rest,
132
+ });
133
+ return Buffer.from(res.data);
134
+ }
135
+
136
+ module.exports = {
137
+ httpPost,
138
+ httpGet,
139
+ httpPut,
140
+ downloadBuffer,
141
+ getSentryTraceHeaders,
142
+ USER_AGENT,
143
+ baseHeaders,
144
+ };