testdriverai 7.6.0-test.6 → 7.6.0-test.7

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 7.6.0-test.7 (2026-03-13)
2
+
3
+ ## 🔧 Maintenance
4
+
5
+ - Eliminate CI race conditions in promotion pipeline and streamline release workflows [CI] (9d83f886)
6
+ - Improve VNC URL display in CI environments [API] (9d83f886)
7
+ - Add dynamic channel resolution system for SDK configuration [SDK] (9d83f886)
8
+ - Update MCP server dependencies and enhance error handling [SDK] (9d83f886)
9
+
1
10
  ## 7.6.0-test.6 (2026-03-13)
2
11
 
3
12
  ## 🔧 Maintenance
@@ -16,7 +16,7 @@ function parseValue(value) {
16
16
  return value;
17
17
  }
18
18
 
19
- const channelConfig = require("../../channel.json");
19
+ const channelConfig = require("../../lib/resolve-channel.js");
20
20
 
21
21
  // Factory function that creates a config instance
22
22
  const createConfig = (environment = {}) => {
@@ -511,7 +511,7 @@ const createSandbox = function (emitter, analytics, sessionInstance) {
511
511
  url = runnerVncUrl;
512
512
  logger.log(`Using runner-provided vncUrl: ${url}`);
513
513
  } else if (runnerIp && noVncPort) {
514
- url = `http://${runnerIp}:${noVncPort}/vnc_lite.html`;
514
+ url = `http://${runnerIp}:${noVncPort}/vnc_lite.html?token=V3b8wG9`;
515
515
  logger.log(`noVNC URL constructed from runner ip+port: ${url}`);
516
516
  } else if (runnerIp) {
517
517
  url = "http://" + runnerIp;
@@ -619,7 +619,7 @@ const createSandbox = function (emitter, analytics, sessionInstance) {
619
619
  }
620
620
 
621
621
  // Construct VNC URL — use port 8080 (nginx noVNC proxy) for Windows instances
622
- var directUrl = message.ip ? "http://" + message.ip + ":8080/vnc_lite.html" : undefined;
622
+ var directUrl = message.ip ? "http://" + message.ip + ":8080/vnc_lite.html?token=V3b8wG9" : undefined;
623
623
 
624
624
  return {
625
625
  success: true,
@@ -12,7 +12,7 @@ const { execSync } = require("child_process");
12
12
  require("dotenv").config();
13
13
 
14
14
  // API configuration
15
- const channelConfig = require("../../../channel.json");
15
+ const channelConfig = require("../../../lib/resolve-channel.js");
16
16
  const API_BASE_URL = process.env.TD_API_ROOT || channelConfig.channels[channelConfig.active];
17
17
  const POLL_INTERVAL = 5000; // 5 seconds
18
18
  const POLL_TIMEOUT = 900000; // 15 minutes
@@ -9,7 +9,7 @@ import { setTestRunInfo } from "./shared-test-state.mjs";
9
9
 
10
10
  // Use createRequire to import CommonJS modules without esbuild processing
11
11
  const require = createRequire(import.meta.url);
12
- const channelConfig = require("../channel.json");
12
+ const channelConfig = require("../lib/resolve-channel.js");
13
13
 
14
14
  // Import Sentry for error reporting
15
15
  const Sentry = require("@sentry/node");
@@ -80,7 +80,7 @@ class Dashcam {
80
80
  * @private
81
81
  */
82
82
  _getApiRoot() {
83
- const channelConfig = require("../../channel.json");
83
+ const channelConfig = require("../../lib/resolve-channel.js");
84
84
  return (
85
85
  this.client.config?.TD_API_ROOT || channelConfig.channels[channelConfig.active]
86
86
  );
@@ -92,7 +92,7 @@ class Dashcam {
92
92
  * @param {string} apiRoot - The API root URL
93
93
  * @returns {string} The corresponding console URL
94
94
  */
95
- static getConsoleUrl(apiRoot = (() => { const c = require("../../channel.json"); return c.channels[c.active]; })()) {
95
+ static getConsoleUrl(apiRoot = (() => { const c = require("../../lib/resolve-channel.js"); return c.channels[c.active]; })()) {
96
96
  // Allow explicit override via env (e.g. VITE_DOMAIN from .env)
97
97
  if (process.env.VITE_DOMAIN) return process.env.VITE_DOMAIN;
98
98
 
@@ -382,6 +382,7 @@ jobs:
382
382
  const addMcpResult = require("child_process").spawnSync(
383
383
  "npx",
384
384
  [
385
+ "--yes",
385
386
  "add-mcp",
386
387
  "testdriver",
387
388
  "--command",
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Resolves the active release channel and API URLs dynamically,
3
+ * eliminating the need for a static channel.json file.
4
+ *
5
+ * Channel is derived from (in priority order):
6
+ * 1. TD_CHANNEL env var (explicit override)
7
+ * 2. SDK package.json version prerelease tag (e.g. "7.6.0-test.5" → "test")
8
+ * 3. "latest" for clean semver versions (stable releases)
9
+ */
10
+
11
+ const semver = require("semver");
12
+
13
+ const CHANNELS = {
14
+ dev: "http://localhost:1337",
15
+ test: "https://api.test.testdriver.ai",
16
+ canary: "https://api.canary.testdriver.ai",
17
+ latest: "https://api.testdriver.ai",
18
+ };
19
+
20
+ function resolveActiveChannel() {
21
+ if (process.env.TD_CHANNEL && CHANNELS[process.env.TD_CHANNEL]) {
22
+ return process.env.TD_CHANNEL;
23
+ }
24
+
25
+ const version = require("../package.json").version;
26
+ const pre = semver.prerelease(version);
27
+ if (pre && pre.length > 0 && CHANNELS[pre[0]]) {
28
+ return pre[0];
29
+ }
30
+
31
+ return "latest";
32
+ }
33
+
34
+ const active = resolveActiveChannel();
35
+
36
+ module.exports = { active, channels: CHANNELS };
@@ -22,7 +22,7 @@ import TestDriverSDK from "../../sdk.js";
22
22
 
23
23
  // Use createRequire to import CommonJS modules
24
24
  const require = createRequire(import.meta.url);
25
- const channelConfig = require("../../channel.json");
25
+ const channelConfig = require("../../lib/resolve-channel.js");
26
26
 
27
27
  /**
28
28
  * Minimum required Vitest major version
@@ -26,8 +26,18 @@ import { sessionManager } from "./session.js";
26
26
  const sdkRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
27
27
  const packageJson = JSON.parse(fs.readFileSync(path.join(sdkRoot, "package.json"), "utf-8"));
28
28
  const version = packageJson.version || "1.0.0";
29
- const channelConfig = JSON.parse(fs.readFileSync(path.join(sdkRoot, "channel.json"), "utf-8"));
30
- const releaseChannel = channelConfig.active || "dev";
29
+ // Derive release channel from package version prerelease tag (e.g. "7.6.0-test.5" "test")
30
+ import semver from "semver";
31
+ const KNOWN_CHANNELS = new Set(["dev", "test", "canary", "latest"]);
32
+ function resolveReleaseChannel(ver) {
33
+ if (process.env.TD_CHANNEL && KNOWN_CHANNELS.has(process.env.TD_CHANNEL))
34
+ return process.env.TD_CHANNEL;
35
+ const pre = semver.prerelease(ver);
36
+ if (pre && pre.length > 0 && KNOWN_CHANNELS.has(String(pre[0])))
37
+ return String(pre[0]);
38
+ return "latest";
39
+ }
40
+ const releaseChannel = resolveReleaseChannel(version);
31
41
  const isSentryEnabled = () => {
32
42
  if (process.env.TD_TELEMETRY === "false") {
33
43
  return false;
@@ -11,10 +11,12 @@
11
11
  "@modelcontextprotocol/ext-apps": "^1.0.0",
12
12
  "@modelcontextprotocol/sdk": "^1.24.0",
13
13
  "@sentry/node": "^9.0.0",
14
+ "semver": "^7.7.4",
14
15
  "zod": "^3.24.0"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@types/node": "^22.0.0",
19
+ "@types/semver": "^7.7.1",
18
20
  "cross-env": "^7.0.3",
19
21
  "tsx": "^4.19.0",
20
22
  "typescript": "^5.6.0",
@@ -1745,6 +1747,13 @@
1745
1747
  "@types/pg": "*"
1746
1748
  }
1747
1749
  },
1750
+ "node_modules/@types/semver": {
1751
+ "version": "7.7.1",
1752
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
1753
+ "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==",
1754
+ "dev": true,
1755
+ "license": "MIT"
1756
+ },
1748
1757
  "node_modules/@types/shimmer": {
1749
1758
  "version": "1.2.0",
1750
1759
  "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz",
@@ -3087,9 +3096,9 @@
3087
3096
  "license": "MIT"
3088
3097
  },
3089
3098
  "node_modules/semver": {
3090
- "version": "7.7.3",
3091
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
3092
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
3099
+ "version": "7.7.4",
3100
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
3101
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
3093
3102
  "license": "ISC",
3094
3103
  "bin": {
3095
3104
  "semver": "bin/semver.js"
@@ -16,10 +16,12 @@
16
16
  "@modelcontextprotocol/ext-apps": "^1.0.0",
17
17
  "@modelcontextprotocol/sdk": "^1.24.0",
18
18
  "@sentry/node": "^9.0.0",
19
+ "semver": "^7.7.4",
19
20
  "zod": "^3.24.0"
20
21
  },
21
22
  "devDependencies": {
22
23
  "@types/node": "^22.0.0",
24
+ "@types/semver": "^7.7.1",
23
25
  "cross-env": "^7.0.3",
24
26
  "tsx": "^4.19.0",
25
27
  "typescript": "^5.6.0",
@@ -33,8 +33,17 @@ import { sessionManager, type SessionState } from "./session.js";
33
33
  const sdkRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
34
34
  const packageJson = JSON.parse(fs.readFileSync(path.join(sdkRoot, "package.json"), "utf-8"));
35
35
  const version = packageJson.version || "1.0.0";
36
- const channelConfig = JSON.parse(fs.readFileSync(path.join(sdkRoot, "channel.json"), "utf-8"));
37
- const releaseChannel = channelConfig.active || "dev";
36
+
37
+ // Derive release channel from package version prerelease tag (e.g. "7.6.0-test.5" "test")
38
+ import semver from "semver";
39
+ const KNOWN_CHANNELS = new Set(["dev", "test", "canary", "latest"]);
40
+ function resolveReleaseChannel(ver: string): string {
41
+ if (process.env.TD_CHANNEL && KNOWN_CHANNELS.has(process.env.TD_CHANNEL)) return process.env.TD_CHANNEL;
42
+ const pre = semver.prerelease(ver);
43
+ if (pre && pre.length > 0 && KNOWN_CHANNELS.has(String(pre[0]))) return String(pre[0]);
44
+ return "latest";
45
+ }
46
+ const releaseChannel = resolveReleaseChannel(version);
38
47
 
39
48
  const isSentryEnabled = () => {
40
49
  if (process.env.TD_TELEMETRY === "false") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "7.6.0-test.6",
3
+ "version": "7.6.0-test.7",
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",
@@ -85,8 +85,8 @@
85
85
  "@octokit/rest": "^20.1.1",
86
86
  "@sentry/node": "^9.47.1",
87
87
  "@stoplight/yaml-ast-parser": "^0.0.50",
88
- "ajv": "^8.17.1",
89
88
  "ably": "^2.6.0",
89
+ "ajv": "^8.17.1",
90
90
  "arktype": "^2.1.19",
91
91
  "axios": "^1.7.7",
92
92
  "chalk": "^4.1.2",
@@ -105,6 +105,7 @@
105
105
  "pixelmatch": "^7.1.0",
106
106
  "remark-parse": "^11.0.0",
107
107
  "sanitize-filename": "^1.6.3",
108
+ "semver": "^7.7.4",
108
109
  "strip-ansi": "^6.0.1",
109
110
  "terminal-image": "^4.1.0",
110
111
  "tmp": "^0.2.3",
package/sdk.js CHANGED
@@ -1438,7 +1438,7 @@ class TestDriverSDK {
1438
1438
  }
1439
1439
 
1440
1440
  // Set up environment with API key
1441
- const channelConfig = require("./channel.json");
1441
+ const channelConfig = require("./lib/resolve-channel.js");
1442
1442
  const environment = {
1443
1443
  TD_API_KEY: resolvedApiKey,
1444
1444
  TD_API_ROOT: options.apiRoot || process.env.TD_API_ROOT || channelConfig.channels[channelConfig.active],
package/channel.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "active": "test",
3
- "channels": {
4
- "dev": "http://localhost:1337",
5
- "test": "https://api.test.testdriver.ai",
6
- "canary": "https://api.canary.testdriver.ai",
7
- "latest": "https://api.testdriver.ai"
8
- }
9
- }