qraftai-runner 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +57 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@ import { createRequire } from "node:module";
7
7
  import { writeFileSync, existsSync, statSync, mkdirSync } from "node:fs";
8
8
  import { tmpdir } from "node:os";
9
9
  import { join } from "node:path";
10
+ import { execFile as execFile2 } from "node:child_process";
11
+ import { promisify as promisify2 } from "node:util";
10
12
 
11
13
  // ../server/mobile/appiumManager.js
12
14
  import { spawn } from "node:child_process";
@@ -1070,6 +1072,7 @@ var AppiumDriver = class extends AutomationDriver {
1070
1072
  };
1071
1073
 
1072
1074
  // index.js
1075
+ var pexec2 = promisify2(execFile2);
1073
1076
  var VERSION = (() => {
1074
1077
  const req = createRequire(import.meta.url);
1075
1078
  for (const p of ["./package.json", "../package.json"]) {
@@ -1087,10 +1090,49 @@ function parseArgs(argv) {
1087
1090
  if (a === "--server" || a === "-s") out.server = argv[++i];
1088
1091
  else if (a === "--token" || a === "-t") out.token = argv[++i];
1089
1092
  else if (a === "--name" || a === "-n") out.name = argv[++i];
1093
+ else if (a === "--check" || a === "--doctor") out.check = true;
1094
+ else if (a === "--skip-check") out.skipCheck = true;
1090
1095
  else if (a === "--help" || a === "-h") out.help = true;
1091
1096
  }
1092
1097
  return out;
1093
1098
  }
1099
+ async function have(cmd, cmdArgs, re) {
1100
+ try {
1101
+ const { stdout, stderr } = await pexec2(cmd, cmdArgs, { timeout: 8e3 });
1102
+ return re ? re.test(`${stdout || ""}${stderr || ""}`) : true;
1103
+ } catch {
1104
+ return false;
1105
+ }
1106
+ }
1107
+ async function preflight() {
1108
+ const java = await have("java", ["-version"]);
1109
+ const adb = await have("adb", ["version"]);
1110
+ const appium = await have("appium", ["--version"]);
1111
+ const uia = appium ? await have("appium", ["driver", "list", "--installed"], /uiautomator2/i) : false;
1112
+ let device = false;
1113
+ try {
1114
+ device = (await listAdbDevices()).length > 0 || (await listAvds()).length > 0;
1115
+ } catch {
1116
+ }
1117
+ return [
1118
+ { label: "Java (JDK 17+)", ok: java, critical: false, hint: "install a JDK 17+ (e.g. brew install openjdk)" },
1119
+ { label: "adb (Android SDK platform-tools)", ok: adb, critical: true, hint: "install Android SDK; add platform-tools to PATH + set ANDROID_HOME" },
1120
+ { label: "Appium 2", ok: appium, critical: true, hint: "npm i -g appium" },
1121
+ { label: "uiautomator2 driver", ok: uia, critical: true, hint: "appium driver install uiautomator2" },
1122
+ { label: "A device (booted emulator / USB phone)", ok: device, critical: false, hint: "boot an emulator or plug in a phone with USB debugging" }
1123
+ ];
1124
+ }
1125
+ function reportPreflight(checks) {
1126
+ console.log("\nPrerequisite check:");
1127
+ let criticalMissing = false, deviceMissing = false;
1128
+ for (const c of checks) {
1129
+ console.log(` ${c.ok ? "\u2713" : "\u2717"} ${c.label}${c.ok ? "" : ` \u2192 ${c.hint}`}`);
1130
+ if (!c.ok && c.critical) criticalMissing = true;
1131
+ if (!c.ok && !c.critical && /device/i.test(c.label)) deviceMissing = true;
1132
+ }
1133
+ if (!criticalMissing && deviceMissing) console.log(" (no device yet \u2014 connect one and it'll appear on \u21BB Recheck in the app)");
1134
+ return { criticalMissing };
1135
+ }
1094
1136
  var args = parseArgs(process.argv.slice(2));
1095
1137
  if (args.help) {
1096
1138
  console.log(`QraftAI Runner v${VERSION}
@@ -1103,11 +1145,18 @@ Options:
1103
1145
  -s, --server wss://<your-qraftai-host>/runner-stream (or QRAFTAI_SERVER)
1104
1146
  -t, --token org-scoped runner token from the Mobile tab (or QRAFTAI_TOKEN)
1105
1147
  -n, --name a label shown in the app for this machine (or QRAFTAI_RUNNER_NAME)
1148
+ --check check prerequisites and exit (no connection; also --doctor)
1149
+ --skip-check connect without the startup prerequisite check
1106
1150
 
1107
1151
  Prerequisites (on this machine): JDK 17+, Android SDK (adb + emulator),
1108
1152
  Appium 2 + uiautomator2, and a device (AVD or USB phone with USB debugging).`);
1109
1153
  process.exit(0);
1110
1154
  }
1155
+ if (args.check) {
1156
+ const { criticalMissing } = reportPreflight(await preflight());
1157
+ console.log(criticalMissing ? "\n\u2716 Missing required tools above.\n" : "\n\u2713 Ready to run the runner.\n");
1158
+ process.exit(criticalMissing ? 1 : 0);
1159
+ }
1111
1160
  var SERVER = args.server || process.env.QRAFTAI_SERVER;
1112
1161
  var TOKEN = args.token || process.env.QRAFTAI_TOKEN;
1113
1162
  var NAME = args.name || process.env.QRAFTAI_RUNNER_NAME || "";
@@ -1296,4 +1345,12 @@ async function shutdown() {
1296
1345
  }
1297
1346
  process.on("SIGINT", shutdown);
1298
1347
  process.on("SIGTERM", shutdown);
1348
+ if (!args.skipCheck) {
1349
+ const { criticalMissing } = reportPreflight(await preflight());
1350
+ if (criticalMissing) {
1351
+ console.error("\n\u2716 Fix the required tools above, then re-run. (bypass with --skip-check)\n");
1352
+ process.exit(1);
1353
+ }
1354
+ console.log("");
1355
+ }
1299
1356
  connect();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qraftai-runner",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "QraftAI local device runner — bridge your own Android emulator/phone to a QraftAI workspace.",
5
5
  "type": "module",
6
6
  "bin": {