@yoqa/runner 1.0.4 → 1.0.5

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 +207 -188
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18066,9 +18066,47 @@ var require_src5 = __commonJS((exports) => {
18066
18066
 
18067
18067
  // src/domains/android-toolchain/android-sdk.ts
18068
18068
  import { existsSync } from "fs";
18069
+ import { homedir as homedir2 } from "os";
18070
+ import { posix as posix2, win32 as win322 } from "path";
18071
+
18072
+ // src/domains/android-toolchain/host-path.ts
18069
18073
  import { homedir } from "os";
18070
- import { join } from "path";
18071
- function defaultAndroidSdkRoot(home = homedir(), platform = process.platform, localAppData) {
18074
+ import { posix, win32 } from "path";
18075
+ function pathDelimiter(platform = process.platform) {
18076
+ return platform === "win32" ? win32.delimiter : posix.delimiter;
18077
+ }
18078
+ function prependPathEntries(currentPath, entries, platform = process.platform) {
18079
+ const delimiter = pathDelimiter(platform);
18080
+ const existing = currentPath.split(delimiter).filter(Boolean);
18081
+ const prepend = entries.filter((dir) => !existing.includes(dir));
18082
+ return [...prepend, ...existing].join(delimiter);
18083
+ }
18084
+ function pathWithHostTools(currentPath = process.env.PATH ?? "", home = homedir(), platform = process.platform) {
18085
+ const { join } = platform === "win32" ? win32 : posix;
18086
+ const extras = [
18087
+ ...platform === "win32" ? [] : ["/opt/homebrew/bin", "/opt/homebrew/sbin", "/usr/local/bin"],
18088
+ join(home, ".local", "bin"),
18089
+ join(home, ".bun", "bin"),
18090
+ join(home, ".opencode", "bin"),
18091
+ join(home, ".grok", "bin"),
18092
+ join(home, ".antigravity", "antigravity", "bin")
18093
+ ];
18094
+ return prependPathEntries(currentPath, extras, platform);
18095
+ }
18096
+ var hostToolPathReady = false;
18097
+ function ensureHostToolPath() {
18098
+ if (hostToolPathReady)
18099
+ return;
18100
+ hostToolPathReady = true;
18101
+ process.env.PATH = pathWithHostTools();
18102
+ }
18103
+
18104
+ // src/domains/android-toolchain/android-sdk.ts
18105
+ function pathModule(platform) {
18106
+ return platform === "win32" ? win322 : posix2;
18107
+ }
18108
+ function defaultAndroidSdkRoot(home = homedir2(), platform = process.platform, localAppData) {
18109
+ const { join } = pathModule(platform);
18072
18110
  if (platform === "win32") {
18073
18111
  const base = localAppData || join(home, "AppData", "Local");
18074
18112
  return join(base, "Android", "Sdk");
@@ -18079,6 +18117,7 @@ function defaultAndroidSdkRoot(home = homedir(), platform = process.platform, lo
18079
18117
  return join(home, "Android", "Sdk");
18080
18118
  }
18081
18119
  function defaultJavaHomeCandidates(home, platform = process.platform) {
18120
+ const { join } = pathModule(platform);
18082
18121
  if (platform === "darwin") {
18083
18122
  return [
18084
18123
  join("/Applications", "Android Studio.app", "Contents", "jbr", "Contents", "Home"),
@@ -18101,28 +18140,29 @@ function resolveAndroidSdkRoot(env = {
18101
18140
  const fromEnv = env.ANDROID_HOME?.trim() || env.ANDROID_SDK_ROOT?.trim();
18102
18141
  if (fromEnv)
18103
18142
  return fromEnv;
18104
- const home = options?.home ?? homedir();
18143
+ const home = options?.home ?? homedir2();
18105
18144
  const platform = options?.platform ?? process.platform;
18106
18145
  return defaultAndroidSdkRoot(home, platform, options?.localAppData);
18107
18146
  }
18108
- function androidSdkBinDirs(sdkRoot) {
18147
+ function androidSdkBinDirs(sdkRoot, platform = process.platform) {
18148
+ const { join } = pathModule(platform);
18109
18149
  return [
18110
18150
  join(sdkRoot, "platform-tools"),
18111
18151
  join(sdkRoot, "cmdline-tools", "latest", "bin"),
18112
18152
  join(sdkRoot, "emulator")
18113
18153
  ];
18114
18154
  }
18115
- function pathWithAndroidSdk(currentPath, sdkRoot) {
18116
- const extras = androidSdkBinDirs(sdkRoot);
18117
- const existing = currentPath.split(":").filter(Boolean);
18118
- const prepend = extras.filter((dir) => !existing.includes(dir));
18119
- return [...prepend, ...existing].join(":");
18155
+ function androidSdkToolPath(sdkRoot, subdir, name, platform = process.platform) {
18156
+ return pathModule(platform).join(sdkRoot, subdir, platform === "win32" ? `${name}.exe` : name);
18157
+ }
18158
+ function pathWithAndroidSdk(currentPath, sdkRoot, platform = process.platform) {
18159
+ return prependPathEntries(currentPath, androidSdkBinDirs(sdkRoot, platform), platform);
18120
18160
  }
18121
18161
  function androidSdkEnvPatch(env, options) {
18122
18162
  const patch = {};
18123
18163
  const resolved = resolveAndroidSdkRoot(env, options);
18124
18164
  if (resolved && options.pathExists(resolved)) {
18125
- patch.PATH = pathWithAndroidSdk(env.PATH ?? "", resolved);
18165
+ patch.PATH = pathWithAndroidSdk(env.PATH ?? "", resolved, options.platform);
18126
18166
  if (!env.ANDROID_HOME?.trim() && !env.ANDROID_SDK_ROOT?.trim()) {
18127
18167
  patch.ANDROID_HOME = resolved;
18128
18168
  patch.ANDROID_SDK_ROOT = resolved;
@@ -18165,7 +18205,7 @@ function androidProcessEnv(env = process.env, options) {
18165
18205
  JAVA_HOME: next.JAVA_HOME,
18166
18206
  PATH: next.PATH
18167
18207
  }, {
18168
- home: options?.home ?? homedir(),
18208
+ home: options?.home ?? homedir2(),
18169
18209
  platform: options?.platform ?? process.platform,
18170
18210
  localAppData: next.LOCALAPPDATA,
18171
18211
  pathExists: options?.pathExists ?? existsSync
@@ -18184,37 +18224,11 @@ function ensureAndroidSdkEnv() {
18184
18224
  process.env.PATH = next.PATH;
18185
18225
  }
18186
18226
 
18187
- // src/domains/android-toolchain/host-path.ts
18188
- import { homedir as homedir2 } from "os";
18189
- import { join as join2 } from "path";
18190
- function pathWithHostTools(currentPath = process.env.PATH ?? "", home = homedir2()) {
18191
- const extras = [
18192
- "/opt/homebrew/bin",
18193
- "/opt/homebrew/sbin",
18194
- "/usr/local/bin",
18195
- join2(home, ".local", "bin"),
18196
- join2(home, ".bun", "bin"),
18197
- join2(home, ".opencode", "bin"),
18198
- join2(home, ".grok", "bin"),
18199
- join2(home, ".antigravity", "antigravity", "bin")
18200
- ];
18201
- const existing = currentPath.split(":").filter(Boolean);
18202
- const prepend = extras.filter((dir) => !existing.includes(dir));
18203
- return [...prepend, ...existing].join(":");
18204
- }
18205
- var hostToolPathReady = false;
18206
- function ensureHostToolPath() {
18207
- if (hostToolPathReady)
18208
- return;
18209
- hostToolPathReady = true;
18210
- process.env.PATH = pathWithHostTools();
18211
- }
18212
-
18213
18227
  // src/domains/catalog/db.ts
18214
18228
  import { Database as Database2 } from "bun:sqlite";
18215
18229
  import { mkdirSync } from "fs";
18216
18230
  import { homedir as homedir3 } from "os";
18217
- import { dirname, join as join3 } from "path";
18231
+ import { dirname, join } from "path";
18218
18232
 
18219
18233
  // ../../node_modules/drizzle-orm/bun-sqlite/driver.js
18220
18234
  import { Database } from "bun:sqlite";
@@ -18850,7 +18864,7 @@ function sql(strings, ...params) {
18850
18864
  return new SQL([new StringChunk(str)]);
18851
18865
  }
18852
18866
  sql2.raw = raw;
18853
- function join3(chunks, separator) {
18867
+ function join(chunks, separator) {
18854
18868
  const result = [];
18855
18869
  for (const [i, chunk] of chunks.entries()) {
18856
18870
  if (i > 0 && separator !== undefined) {
@@ -18860,7 +18874,7 @@ function sql(strings, ...params) {
18860
18874
  }
18861
18875
  return new SQL(result);
18862
18876
  }
18863
- sql2.join = join3;
18877
+ sql2.join = join;
18864
18878
  function identifier(value) {
18865
18879
  return new Name(value);
18866
18880
  }
@@ -21094,7 +21108,7 @@ class SQLiteSelectQueryBuilderBase extends TypedQueryBuilder {
21094
21108
  const tableName = getTableLikeName(table);
21095
21109
  for (const item of extractUsedTable(table))
21096
21110
  this.usedTables.add(item);
21097
- if (typeof tableName === "string" && this.config.joins?.some((join3) => join3.alias === tableName)) {
21111
+ if (typeof tableName === "string" && this.config.joins?.some((join) => join.alias === tableName)) {
21098
21112
  throw new Error(`Alias "${tableName}" is already used in this query`);
21099
21113
  }
21100
21114
  if (!this.isPartialSelect) {
@@ -21508,7 +21522,7 @@ class SQLiteUpdateBase extends QueryPromise {
21508
21522
  createJoin(joinType) {
21509
21523
  return (table, on) => {
21510
21524
  const tableName = getTableLikeName(table);
21511
- if (typeof tableName === "string" && this.config.joins.some((join3) => join3.alias === tableName)) {
21525
+ if (typeof tableName === "string" && this.config.joins.some((join) => join.alias === tableName)) {
21512
21526
  throw new Error(`Alias "${tableName}" is already used in this query`);
21513
21527
  }
21514
21528
  if (typeof on === "function") {
@@ -22376,8 +22390,8 @@ var runSteps = sqliteTable("run_steps", {
22376
22390
 
22377
22391
  // src/domains/catalog/db.ts
22378
22392
  var drizzleSchema = { ...exports_schema3, ...exports_schema2, ...exports_schema4, ...exports_schema };
22379
- var YOQA_ROOT = join3(homedir3(), ".yoqa");
22380
- var DEFAULT_DB_PATH = join3(YOQA_ROOT, "yoqa.db");
22393
+ var YOQA_ROOT = join(homedir3(), ".yoqa");
22394
+ var DEFAULT_DB_PATH = join(YOQA_ROOT, "yoqa.db");
22381
22395
  var catalogDb = null;
22382
22396
  var sqliteClient = null;
22383
22397
  function ensureSchema(sqlite) {
@@ -22719,7 +22733,7 @@ function getCatalogDb() {
22719
22733
  }
22720
22734
 
22721
22735
  // src/domains/runs/application.ts
22722
- import { existsSync as existsSync9 } from "fs";
22736
+ import { existsSync as existsSync10 } from "fs";
22723
22737
 
22724
22738
  // ../../node_modules/zod/v3/external.js
22725
22739
  var exports_external = {};
@@ -27838,9 +27852,10 @@ function startTargetRequest(platform, target) {
27838
27852
  import { basename, extname } from "path";
27839
27853
 
27840
27854
  // src/domains/devices/application.ts
27855
+ import { existsSync as existsSync2 } from "fs";
27841
27856
  import { mkdtemp as mkdtemp2, readFile as readFile2, rm as rm2 } from "fs/promises";
27842
27857
  import { tmpdir as tmpdir2 } from "os";
27843
- import { join as join5 } from "path";
27858
+ import { isAbsolute, join as join3 } from "path";
27844
27859
 
27845
27860
  // src/domains/devices/android-identity.ts
27846
27861
  function matchAndroidIdentity(deviceId, connected, knownAvds = []) {
@@ -27872,7 +27887,7 @@ function parseAdbEmuAvdName(stdout) {
27872
27887
  import { constants } from "fs";
27873
27888
  import { access, mkdtemp, readFile, rm } from "fs/promises";
27874
27889
  import { homedir as homedir4, tmpdir } from "os";
27875
- import { join as join4 } from "path";
27890
+ import { join as join2 } from "path";
27876
27891
  var KNOWN_BROWSERS = [
27877
27892
  { id: "web-chrome", name: "Google Chrome", app: "Google Chrome" },
27878
27893
  { id: "web-edge", name: "Microsoft Edge", app: "Microsoft Edge" },
@@ -27892,17 +27907,17 @@ function discoveryDeps() {
27892
27907
  }
27893
27908
  var VERSION_RE = /<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/;
27894
27909
  async function bundleVersion(appPath, deps) {
27895
- const plist = await deps.readText(join4(appPath, "Contents/Info.plist")).catch(() => "");
27910
+ const plist = await deps.readText(join2(appPath, "Contents/Info.plist")).catch(() => "");
27896
27911
  return VERSION_RE.exec(plist)?.[1]?.trim() || null;
27897
27912
  }
27898
27913
  async function findInstalledBrowsers(deps = discoveryDeps()) {
27899
27914
  if (deps.platform !== "darwin")
27900
27915
  return [];
27901
- const roots = ["/Applications", join4(deps.home, "Applications")];
27916
+ const roots = ["/Applications", join2(deps.home, "Applications")];
27902
27917
  const found = await Promise.all(KNOWN_BROWSERS.map(async ({ id, name, app }) => {
27903
27918
  for (const root of roots) {
27904
- const appPath = join4(root, `${app}.app`);
27905
- const executable = join4(appPath, "Contents/MacOS", app);
27919
+ const appPath = join2(root, `${app}.app`);
27920
+ const executable = join2(appPath, "Contents/MacOS", app);
27906
27921
  if (!await deps.isExecutable(executable))
27907
27922
  continue;
27908
27923
  return { id, name, version: await bundleVersion(appPath, deps), executable };
@@ -27947,7 +27962,7 @@ function spawnBrowser(command) {
27947
27962
  return Bun.spawn(command, { stdin: "ignore", stdout: "ignore", stderr: "pipe" });
27948
27963
  }
27949
27964
  async function readActivePort(profileDir) {
27950
- const text2 = await readFile(join4(profileDir, "DevToolsActivePort"), "utf8").catch(() => "");
27965
+ const text2 = await readFile(join2(profileDir, "DevToolsActivePort"), "utf8").catch(() => "");
27951
27966
  const [port, path] = text2.split(`
27952
27967
  `).map((line) => line.trim());
27953
27968
  if (!port || !/^\d+$/.test(port) || !path?.startsWith("/"))
@@ -27957,7 +27972,7 @@ async function readActivePort(profileDir) {
27957
27972
  async function launchChromium(browser, deps = {}) {
27958
27973
  const spawn = deps.spawn ?? spawnBrowser;
27959
27974
  const readyTimeoutMs = deps.readyTimeoutMs ?? READY_TIMEOUT_MS;
27960
- const profileDir = await mkdtemp(join4(tmpdir(), "yoqa-web-"));
27975
+ const profileDir = await mkdtemp(join2(tmpdir(), "yoqa-web-"));
27961
27976
  const removeProfile = () => rm(profileDir, { recursive: true, force: true });
27962
27977
  let proc;
27963
27978
  try {
@@ -28134,19 +28149,27 @@ async function resolveTool(candidates) {
28134
28149
  for (const candidate of candidates) {
28135
28150
  if (!candidate)
28136
28151
  continue;
28137
- const { exitCode } = await runCommand(["test", "-x", candidate]);
28138
- if (exitCode === 0)
28139
- return candidate;
28152
+ if (isAbsolute(candidate)) {
28153
+ if (existsSync2(candidate))
28154
+ return candidate;
28155
+ continue;
28156
+ }
28157
+ const onPath = Bun.which(candidate);
28158
+ if (onPath)
28159
+ return onPath;
28140
28160
  }
28141
28161
  return null;
28142
28162
  }
28143
28163
  async function resolveAdb() {
28144
28164
  const sdk = androidSdkRoot();
28145
- return resolveTool([...sdk ? [join5(sdk, "platform-tools/adb")] : [], "adb"]);
28165
+ return resolveTool([...sdk ? [androidSdkToolPath(sdk, "platform-tools", "adb")] : [], "adb"]);
28146
28166
  }
28147
28167
  async function resolveEmulator() {
28148
28168
  const sdk = androidSdkRoot();
28149
- return resolveTool([...sdk ? [join5(sdk, "emulator/emulator")] : [], "emulator"]);
28169
+ return resolveTool([
28170
+ ...sdk ? [androidSdkToolPath(sdk, "emulator", "emulator")] : [],
28171
+ "emulator"
28172
+ ]);
28150
28173
  }
28151
28174
  function formatIosVersion2(version2) {
28152
28175
  const trimmed = version2.trim();
@@ -28250,8 +28273,8 @@ async function readDevicectlDevices(jsonPath) {
28250
28273
  }
28251
28274
  }
28252
28275
  async function listIosPhysicalDevices(includeUnavailable) {
28253
- const dir = await mkdtemp2(join5(tmpdir2(), "yoqa-devices-"));
28254
- const jsonPath = join5(dir, "devices.json");
28276
+ const dir = await mkdtemp2(join3(tmpdir2(), "yoqa-devices-"));
28277
+ const jsonPath = join3(dir, "devices.json");
28255
28278
  try {
28256
28279
  let parsed = await readDevicectlDevices(jsonPath);
28257
28280
  if (parsed === null)
@@ -28315,9 +28338,9 @@ function humanizeModel(model) {
28315
28338
  }
28316
28339
  async function findAvdConfigPath(avdName) {
28317
28340
  const home = process.env.HOME ?? "";
28318
- const roots = [join5(home, ".android/avd"), join5(home, "Library/Android/sdk/.android/avd")];
28341
+ const roots = [join3(home, ".android/avd"), join3(home, "Library/Android/sdk/.android/avd")];
28319
28342
  for (const root of roots) {
28320
- const direct = join5(root, `${avdName}.avd`, "config.ini");
28343
+ const direct = join3(root, `${avdName}.avd`, "config.ini");
28321
28344
  try {
28322
28345
  await readFile2(direct, "utf8");
28323
28346
  return direct;
@@ -28325,7 +28348,7 @@ async function findAvdConfigPath(avdName) {
28325
28348
  try {
28326
28349
  const glob = new Bun.Glob("*.avd/config.ini");
28327
28350
  for await (const match of glob.scan({ cwd: root, onlyFiles: true })) {
28328
- const path = join5(root, match);
28351
+ const path = join3(root, match);
28329
28352
  const text2 = await readFile2(path, "utf8");
28330
28353
  const idLine = text2.split(`
28331
28354
  `).find((line) => line.startsWith("AvdId="));
@@ -28854,7 +28877,7 @@ function normalizeVisionJson(value) {
28854
28877
  import { mkdtemp as mkdtemp3, readFile as readFile3, rm as rm3, writeFile } from "fs/promises";
28855
28878
  import { homedir as homedir5 } from "os";
28856
28879
  import { tmpdir as tmpdir3 } from "os";
28857
- import { join as join6 } from "path";
28880
+ import { join as join4 } from "path";
28858
28881
 
28859
28882
  // ../../node_modules/@ai-sdk/gateway/node_modules/@ai-sdk/provider/dist/index.js
28860
28883
  var marker = "vercel.ai.error";
@@ -51531,9 +51554,9 @@ async function prepareVisionImage(pngBase64) {
51531
51554
  if (process.platform !== "darwin") {
51532
51555
  return { base64: pngBase64, mediaType: "image/png" };
51533
51556
  }
51534
- const dir = await mkdtemp3(join6(tmpdir3(), "yoqa-vision-"));
51535
- const inPath = join6(dir, "shot.png");
51536
- const outPath = join6(dir, "shot.jpg");
51557
+ const dir = await mkdtemp3(join4(tmpdir3(), "yoqa-vision-"));
51558
+ const inPath = join4(dir, "shot.png");
51559
+ const outPath = join4(dir, "shot.jpg");
51537
51560
  try {
51538
51561
  await writeFile(inPath, new Uint8Array(bytes));
51539
51562
  const proc = Bun.spawn([
@@ -51749,8 +51772,8 @@ function openCodeAuthPaths() {
51749
51772
  const paths = [];
51750
51773
  const xdg = process.env.XDG_DATA_HOME?.trim();
51751
51774
  if (xdg)
51752
- paths.push(join6(xdg, "opencode", "auth.json"));
51753
- paths.push(join6(homedir5(), ".local", "share", "opencode", "auth.json"));
51775
+ paths.push(join4(xdg, "opencode", "auth.json"));
51776
+ paths.push(join4(homedir5(), ".local", "share", "opencode", "auth.json"));
51754
51777
  return paths;
51755
51778
  }
51756
51779
  function apiKeyFromOpenCodeAuthEntry(value) {
@@ -60962,7 +60985,7 @@ var anthropic = createAnthropic();
60962
60985
  import { constants as constants2 } from "fs";
60963
60986
  import { access as access2 } from "fs/promises";
60964
60987
  import { homedir as homedir6 } from "os";
60965
- import { isAbsolute, join as join7 } from "path";
60988
+ import { isAbsolute as isAbsolute2, join as join5 } from "path";
60966
60989
  async function pathExists(path) {
60967
60990
  try {
60968
60991
  await access2(path, constants2.F_OK);
@@ -60989,11 +61012,11 @@ async function which(binary) {
60989
61012
  }
60990
61013
  function knownHomeBinCandidates(binaryName, home = homedir6()) {
60991
61014
  return [
60992
- join7(home, ".opencode", "bin", binaryName),
60993
- join7(home, ".grok", "bin", binaryName),
60994
- join7(home, ".antigravity", "antigravity", "bin", binaryName),
60995
- join7(home, ".local", "bin", binaryName),
60996
- join7(home, ".bun", "bin", binaryName),
61015
+ join5(home, ".opencode", "bin", binaryName),
61016
+ join5(home, ".grok", "bin", binaryName),
61017
+ join5(home, ".antigravity", "antigravity", "bin", binaryName),
61018
+ join5(home, ".local", "bin", binaryName),
61019
+ join5(home, ".bun", "bin", binaryName),
60997
61020
  `/opt/homebrew/bin/${binaryName}`,
60998
61021
  `/usr/local/bin/${binaryName}`
60999
61022
  ];
@@ -61008,7 +61031,7 @@ async function resolveFromKnownBins(binaryName) {
61008
61031
  }
61009
61032
  async function resolveBinary(defaultName, binaryPath) {
61010
61033
  const candidate = binaryPath?.trim() || defaultName;
61011
- if (isAbsolute(candidate) || candidate.includes("/")) {
61034
+ if (isAbsolute2(candidate) || candidate.includes("/")) {
61012
61035
  if (await pathExists(candidate)) {
61013
61036
  return { path: candidate, detail: `Found at ${candidate}` };
61014
61037
  }
@@ -61260,7 +61283,7 @@ function resolveAgyModelId(raw, fallback = ANTIGRAVITY_DEFAULT_VISION_MODEL) {
61260
61283
  // src/domains/providers/drivers/antigravity-vision.ts
61261
61284
  import { mkdtemp as mkdtemp4, rm as rm4, writeFile as writeFile2 } from "fs/promises";
61262
61285
  import { tmpdir as tmpdir4 } from "os";
61263
- import { join as join8 } from "path";
61286
+ import { join as join6 } from "path";
61264
61287
 
61265
61288
  // ../../node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider/dist/index.js
61266
61289
  var marker29 = "vercel.ai.error";
@@ -70735,8 +70758,8 @@ async function completeWithAgyCli(input, repairHint) {
70735
70758
  const image = input.image ?? await prepareVisionImage(input.imageBase64);
70736
70759
  const model = resolveAgyModelId(input.auth.defaultModel);
70737
70760
  const ext = image.mediaType === "image/jpeg" ? "jpg" : "png";
70738
- const dir = await mkdtemp4(join8(tmpdir4(), "yoqa-agy-"));
70739
- const shotPath = join8(dir, `shot.${ext}`);
70761
+ const dir = await mkdtemp4(join6(tmpdir4(), "yoqa-agy-"));
70762
+ const shotPath = join6(dir, `shot.${ext}`);
70740
70763
  try {
70741
70764
  await writeFile2(shotPath, new Uint8Array(Buffer.from(image.base64, "base64")));
70742
70765
  const userText = [
@@ -79246,7 +79269,7 @@ ${result.stderr}`.toLowerCase();
79246
79269
  // src/domains/providers/drivers/cursor-vision.ts
79247
79270
  import { mkdtemp as mkdtemp5, rm as rm5, writeFile as writeFile3 } from "fs/promises";
79248
79271
  import { tmpdir as tmpdir5 } from "os";
79249
- import { join as join9 } from "path";
79272
+ import { join as join7 } from "path";
79250
79273
  var CURSOR_DEFAULT_VISION_MODEL = "auto";
79251
79274
  var JSON_REPAIR_PROMPT3 = "Your previous reply was not valid JSON for this task. Reply again with ONLY one strict JSON object using double quotes for every key and string (no single quotes, no markdown, no prose).";
79252
79275
  function resolveCursorApiKey(auth) {
@@ -79259,8 +79282,8 @@ async function invokeCursorPrint(input) {
79259
79282
  }
79260
79283
  const model = input.auth.defaultModel?.trim() || CURSOR_DEFAULT_VISION_MODEL;
79261
79284
  const ext = input.mediaType === "image/jpeg" ? "jpg" : "png";
79262
- const dir = await mkdtemp5(join9(tmpdir5(), "yoqa-cursor-"));
79263
- const shotPath = join9(dir, `shot.${ext}`);
79285
+ const dir = await mkdtemp5(join7(tmpdir5(), "yoqa-cursor-"));
79286
+ const shotPath = join7(dir, `shot.${ext}`);
79264
79287
  const apiKey = resolveCursorApiKey(input.auth);
79265
79288
  try {
79266
79289
  await writeFile3(shotPath, new Uint8Array(Buffer.from(input.imageBase64, "base64")));
@@ -99390,7 +99413,7 @@ var openaiDriver = {
99390
99413
 
99391
99414
  // src/domains/providers/drivers/opencode-config.ts
99392
99415
  import { homedir as homedir7 } from "os";
99393
- import { join as join10 } from "path";
99416
+ import { join as join8 } from "path";
99394
99417
  var OPENAI_COMPATIBLE_PACKAGES = new Set([
99395
99418
  "@ai-sdk/openai-compatible",
99396
99419
  "@ai-sdk/openai",
@@ -99418,8 +99441,8 @@ function openCodeConfigPaths() {
99418
99441
  const paths = [];
99419
99442
  const xdg = process.env.XDG_CONFIG_HOME?.trim();
99420
99443
  if (xdg)
99421
- paths.push(join10(xdg, "opencode", "opencode.json"));
99422
- paths.push(join10(homedir7(), ".config", "opencode", "opencode.json"));
99444
+ paths.push(join8(xdg, "opencode", "opencode.json"));
99445
+ paths.push(join8(homedir7(), ".config", "opencode", "opencode.json"));
99423
99446
  return paths;
99424
99447
  }
99425
99448
  function parseOpenCodeCompatibleProvider(config2, providerId) {
@@ -101680,8 +101703,8 @@ function abortAllMjpegProxies() {
101680
101703
  }
101681
101704
 
101682
101705
  // src/domains/devices/android-devtools.ts
101683
- import { existsSync as existsSync2 } from "fs";
101684
- import { join as join11 } from "path";
101706
+ import { existsSync as existsSync3 } from "fs";
101707
+ import { join as join9 } from "path";
101685
101708
  function escapeAttr(value) {
101686
101709
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
101687
101710
  }
@@ -101715,8 +101738,8 @@ function resolveDevtoolsApk() {
101715
101738
  const fromEnv = process.env.YOQA_ANDROID_DEVTOOLS_APK?.trim();
101716
101739
  if (fromEnv)
101717
101740
  return fromEnv;
101718
- const built = join11(import.meta.dir, "../../../../../native/android-devtools/app/build/outputs/apk/debug/app-debug.apk");
101719
- return existsSync2(built) ? built : null;
101741
+ const built = join9(import.meta.dir, "../../../../../native/android-devtools/app/build/outputs/apk/debug/app-debug.apk");
101742
+ return existsSync3(built) ? built : null;
101720
101743
  }
101721
101744
  async function adbOk(adb, args, label) {
101722
101745
  const result = await adb(args);
@@ -101837,7 +101860,7 @@ async function startAndroidDevtools(context, deps = {}) {
101837
101860
 
101838
101861
  // src/domains/devices/android-direct-lane.ts
101839
101862
  import { mkdir } from "fs/promises";
101840
- import { dirname as dirname2, join as join13 } from "path";
101863
+ import { dirname as dirname2, join as join11 } from "path";
101841
101864
 
101842
101865
  // src/domains/devices/adb-input.ts
101843
101866
  var ANDROID_KEYCODES = {
@@ -102159,8 +102182,8 @@ async function exitsWithin(proc, ms) {
102159
102182
  // src/domains/devices/screenshot-retention.ts
102160
102183
  import { readdir, stat, unlink } from "fs/promises";
102161
102184
  import { homedir as homedir8 } from "os";
102162
- import { join as join12 } from "path";
102163
- var SCREENSHOT_DIR = join12(homedir8(), ".yoqa", "runs", "screenshots");
102185
+ import { join as join10 } from "path";
102186
+ var SCREENSHOT_DIR = join10(homedir8(), ".yoqa", "runs", "screenshots");
102164
102187
  var SHOT_FILE_RE = /^shot_\d+_[0-9a-f-]+\.png$/i;
102165
102188
  var DEFAULT_RETENTION_DAYS = 7;
102166
102189
  var DAY_MS = 24 * 60 * 60 * 1000;
@@ -102188,7 +102211,7 @@ async function pruneOldRunScreenshots(options = {}) {
102188
102211
  const names = (await readdir(dir)).filter((name30) => SHOT_FILE_RE.test(name30));
102189
102212
  const entries = [];
102190
102213
  for (const name30 of names) {
102191
- const info = await stat(join12(dir, name30));
102214
+ const info = await stat(join10(dir, name30));
102192
102215
  entries.push({ name: name30, mtimeMs: info.mtimeMs });
102193
102216
  }
102194
102217
  let removed = 0;
@@ -102197,7 +102220,7 @@ async function pruneOldRunScreenshots(options = {}) {
102197
102220
  now: options.now ?? Date.now()
102198
102221
  })) {
102199
102222
  try {
102200
- await unlink(join12(dir, name30));
102223
+ await unlink(join10(dir, name30));
102201
102224
  removed += 1;
102202
102225
  } catch {}
102203
102226
  }
@@ -102335,7 +102358,7 @@ async function createAndroidDirectSession(options, deps = {}) {
102335
102358
  const screenshot = async () => {
102336
102359
  await mkdir(SCREENSHOT_DIR, { recursive: true });
102337
102360
  const frame = await captureFrame();
102338
- const path = join13(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
102361
+ const path = join11(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
102339
102362
  await Bun.write(path, Uint8Array.from(Buffer.from(frame.base64, "base64")));
102340
102363
  return { path, base64: frame.base64 };
102341
102364
  };
@@ -102561,7 +102584,7 @@ async function createAndroidDirectSession(options, deps = {}) {
102561
102584
 
102562
102585
  // src/domains/devices/ios-device-lane.ts
102563
102586
  import { mkdir as mkdir5 } from "fs/promises";
102564
- import { join as join19 } from "path";
102587
+ import { join as join17 } from "path";
102565
102588
 
102566
102589
  // src/domains/devices/error-chain.ts
102567
102590
  var MAX_LINKS = 8;
@@ -102592,7 +102615,7 @@ function errorChain(error40) {
102592
102615
  // src/domains/devices/frame-recorder.ts
102593
102616
  import { mkdir as mkdir2, mkdtemp as mkdtemp6, rm as rm6 } from "fs/promises";
102594
102617
  import { tmpdir as tmpdir6 } from "os";
102595
- import { dirname as dirname3, join as join14 } from "path";
102618
+ import { dirname as dirname3, join as join12 } from "path";
102596
102619
  var LAST_FRAME_HOLD_S = 0.5;
102597
102620
  async function encodeWithFfmpeg(ffmpeg, list, out) {
102598
102621
  const proc = Bun.spawn([
@@ -102640,7 +102663,7 @@ async function recordFrames(source, path, deps = realDeps) {
102640
102663
  if (!ffmpeg)
102641
102664
  throw new Error("ffmpeg not found on PATH");
102642
102665
  await mkdir2(dirname3(path), { recursive: true });
102643
- const dir = await mkdtemp6(join14(tmpdir6(), "yoqa-frames-"));
102666
+ const dir = await mkdtemp6(join12(tmpdir6(), "yoqa-frames-"));
102644
102667
  try {
102645
102668
  await source.start?.();
102646
102669
  } catch (error40) {
@@ -102654,7 +102677,7 @@ async function recordFrames(source, path, deps = realDeps) {
102654
102677
  const pullOnce = async () => {
102655
102678
  try {
102656
102679
  for (const frame of await source.pull()) {
102657
- const file2 = join14(dir, `${String(frames.length).padStart(6, "0")}.${frame.ext}`);
102680
+ const file2 = join12(dir, `${String(frames.length).padStart(6, "0")}.${frame.ext}`);
102658
102681
  await Bun.write(file2, frame.bytes);
102659
102682
  frames.push({ file: file2, at: frame.at });
102660
102683
  }
@@ -102685,7 +102708,7 @@ async function recordFrames(source, path, deps = realDeps) {
102685
102708
  lines.push(`file '${frame.file}'`, `duration ${Math.max(seconds, 0.001).toFixed(3)}`);
102686
102709
  }
102687
102710
  lines.push(`file '${frames[frames.length - 1]?.file}'`);
102688
- const list = join14(dir, "frames.txt");
102711
+ const list = join12(dir, "frames.txt");
102689
102712
  await Bun.write(list, `${lines.join(`
102690
102713
  `)}
102691
102714
  `);
@@ -103029,16 +103052,16 @@ async function startPhonePreview(send) {
103029
103052
  // src/domains/devices/ios-direct-lane.ts
103030
103053
  import { mkdir as mkdir3, readFile as readFile4 } from "fs/promises";
103031
103054
  import { tmpdir as tmpdir7 } from "os";
103032
- import { dirname as dirname4, join as join17 } from "path";
103055
+ import { dirname as dirname4, join as join15 } from "path";
103033
103056
 
103034
103057
  // src/domains/devices/idb-companion.ts
103035
- import { existsSync as existsSync3 } from "fs";
103058
+ import { existsSync as existsSync4 } from "fs";
103036
103059
  import { homedir as homedir9 } from "os";
103037
- import { join as join15 } from "path";
103038
- var IDB_COMPANION_HOME = join15(homedir9(), ".yoqa", "idb", "idb_companion");
103039
- var IDB_CLIENT_HOME = join15(homedir9(), ".yoqa", "idb", "venv", "bin", "idb");
103060
+ import { join as join13 } from "path";
103061
+ var IDB_COMPANION_HOME = join13(homedir9(), ".yoqa", "idb", "idb_companion");
103062
+ var IDB_CLIENT_HOME = join13(homedir9(), ".yoqa", "idb", "venv", "bin", "idb");
103040
103063
  var MISSING_IDB_MESSAGE = "idb_companion not found. Install the official facebook/idb v1.6.5 macOS binary from GitHub releases to ~/.yoqa/idb/idb_companion (or set YOQA_IDB_COMPANION). Do not use `brew trust facebook/fb`.";
103041
- function resolveIdbCompanionPath(env = process.env, exists2 = existsSync3, which2 = (name30) => Bun.which(name30)) {
103064
+ function resolveIdbCompanionPath(env = process.env, exists2 = existsSync4, which2 = (name30) => Bun.which(name30)) {
103042
103065
  const fromEnv = env.YOQA_IDB_COMPANION?.trim();
103043
103066
  if (fromEnv)
103044
103067
  return fromEnv;
@@ -103046,7 +103069,7 @@ function resolveIdbCompanionPath(env = process.env, exists2 = existsSync3, which
103046
103069
  return IDB_COMPANION_HOME;
103047
103070
  return which2("idb_companion") ?? undefined;
103048
103071
  }
103049
- function resolveIdbClientPath(env = process.env, exists2 = existsSync3, which2 = (name30) => Bun.which(name30)) {
103072
+ function resolveIdbClientPath(env = process.env, exists2 = existsSync4, which2 = (name30) => Bun.which(name30)) {
103050
103073
  const fromEnv = env.YOQA_IDB?.trim();
103051
103074
  if (fromEnv)
103052
103075
  return fromEnv;
@@ -103054,7 +103077,7 @@ function resolveIdbClientPath(env = process.env, exists2 = existsSync3, which2 =
103054
103077
  return IDB_CLIENT_HOME;
103055
103078
  return which2("idb") ?? undefined;
103056
103079
  }
103057
- function requireIdbBins(env = process.env, exists2 = existsSync3, which2 = (name30) => Bun.which(name30)) {
103080
+ function requireIdbBins(env = process.env, exists2 = existsSync4, which2 = (name30) => Bun.which(name30)) {
103058
103081
  const companion = resolveIdbCompanionPath(env, exists2, which2);
103059
103082
  const client = resolveIdbClientPath(env, exists2, which2);
103060
103083
  if (!companion || !client) {
@@ -103337,8 +103360,8 @@ function cleanPageSource(xml, window2) {
103337
103360
  }
103338
103361
 
103339
103362
  // src/domains/devices/yoqa-sim.ts
103340
- import { existsSync as existsSync4 } from "fs";
103341
- import { join as join16 } from "path";
103363
+ import { existsSync as existsSync5 } from "fs";
103364
+ import { join as join14 } from "path";
103342
103365
 
103343
103366
  class YoqaSimUnreachableError extends Error {
103344
103367
  constructor(message) {
@@ -103359,10 +103382,10 @@ function resolveYoqaSimBin() {
103359
103382
  const fromEnv = process.env.YOQA_SIM_BIN?.trim();
103360
103383
  if (fromEnv)
103361
103384
  return fromEnv;
103362
- const root = join16(import.meta.dir, "../../../../../native/yoqa-sim/.build");
103385
+ const root = join14(import.meta.dir, "../../../../../native/yoqa-sim/.build");
103363
103386
  for (const config2 of ["release", "debug"]) {
103364
- const built = join16(root, config2, "yoqa-sim");
103365
- if (existsSync4(built))
103387
+ const built = join14(root, config2, "yoqa-sim");
103388
+ if (existsSync5(built))
103366
103389
  return built;
103367
103390
  }
103368
103391
  return null;
@@ -103614,7 +103637,7 @@ async function recordViaSimctl(udid, path) {
103614
103637
  };
103615
103638
  }
103616
103639
  async function captureViaSimctl(udid) {
103617
- const dest = join17(tmpdir7(), `yoqa-simctl-${crypto.randomUUID()}.png`);
103640
+ const dest = join15(tmpdir7(), `yoqa-simctl-${crypto.randomUUID()}.png`);
103618
103641
  const proc = Bun.spawn(["xcrun", "simctl", "io", udid, "screenshot", dest], {
103619
103642
  stdout: "pipe",
103620
103643
  stderr: "pipe"
@@ -103697,7 +103720,7 @@ async function createIosDirectSession(options, deps = {}) {
103697
103720
  return lock.withLock(fn);
103698
103721
  };
103699
103722
  const captureViaIdb = async () => {
103700
- const dest = join17(tmpdir7(), `yoqa-idb-${crypto.randomUUID()}.png`);
103723
+ const dest = join15(tmpdir7(), `yoqa-idb-${crypto.randomUUID()}.png`);
103701
103724
  let bytes;
103702
103725
  try {
103703
103726
  const result = await run(["screenshot", dest, "--udid", udid], "idb screenshot");
@@ -103728,7 +103751,7 @@ async function createIosDirectSession(options, deps = {}) {
103728
103751
  const screenshot = async () => {
103729
103752
  await mkdir3(SCREENSHOT_DIR, { recursive: true });
103730
103753
  const frame = await captureFrame();
103731
- const path = join17(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
103754
+ const path = join15(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
103732
103755
  await Bun.write(path, Uint8Array.from(Buffer.from(frame.base64, "base64")));
103733
103756
  return { path, base64: frame.base64 };
103734
103757
  };
@@ -104176,10 +104199,10 @@ async function connectUsbmux(udid, port, socketPath = USBMUXD_SOCKET) {
104176
104199
 
104177
104200
  // src/domains/devices/yoqa-runner.ts
104178
104201
  import { X509Certificate, createHash } from "crypto";
104179
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync, renameSync, rmSync } from "fs";
104202
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync, renameSync, rmSync } from "fs";
104180
104203
  import { copyFile, cp, mkdir as mkdir4, readFile as readFile5, readdir as readdir2, rename, rm as rm7, writeFile as writeFile4 } from "fs/promises";
104181
104204
  import { homedir as homedir10 } from "os";
104182
- import { dirname as dirname5, join as join18, relative } from "path";
104205
+ import { dirname as dirname5, join as join16, relative } from "path";
104183
104206
 
104184
104207
  class YoqaRunnerError extends Error {
104185
104208
  constructor(message) {
@@ -104323,12 +104346,12 @@ async function hashSources(projectDir) {
104323
104346
  }
104324
104347
  for (const entry of entries) {
104325
104348
  if (!IGNORED.has(entry))
104326
- await visit9(join18(path, entry));
104349
+ await visit9(join16(path, entry));
104327
104350
  }
104328
104351
  };
104329
104352
  for (const entry of SOURCE_ENTRIES) {
104330
- const path = join18(projectDir, entry);
104331
- if (existsSync5(path))
104353
+ const path = join16(projectDir, entry);
104354
+ if (existsSync6(path))
104332
104355
  await visit9(path);
104333
104356
  }
104334
104357
  return hash.digest("hex");
@@ -104348,12 +104371,12 @@ function parseProfile(plist) {
104348
104371
  };
104349
104372
  }
104350
104373
  async function readProfiles(products, exec) {
104351
- const platform = join18(products, "Debug-iphoneos");
104374
+ const platform = join16(products, "Debug-iphoneos");
104352
104375
  const apps2 = (await readdir2(platform).catch(() => [])).filter((name30) => name30.endsWith(".app"));
104353
104376
  const profiles = [];
104354
104377
  for (const app of apps2) {
104355
- const path = join18(platform, app, "embedded.mobileprovision");
104356
- if (!existsSync5(path))
104378
+ const path = join16(platform, app, "embedded.mobileprovision");
104379
+ if (!existsSync6(path))
104357
104380
  continue;
104358
104381
  const decoded = await exec(["security", "cms", "-D", "-i", path]);
104359
104382
  const profile = decoded.exitCode === 0 ? parseProfile(decoded.stdout) : null;
@@ -104363,7 +104386,7 @@ async function readProfiles(products, exec) {
104363
104386
  return profiles;
104364
104387
  }
104365
104388
  function usableFor(manifest, udid, now) {
104366
- return manifest.version === MANIFEST_VERSION && existsSync5(manifest.xctestrun) && Date.parse(manifest.profileExpiresAt) > now.getTime() && (manifest.devices === null || manifest.devices.includes(udid));
104389
+ return manifest.version === MANIFEST_VERSION && existsSync6(manifest.xctestrun) && Date.parse(manifest.profileExpiresAt) > now.getTime() && (manifest.devices === null || manifest.devices.includes(udid));
104367
104390
  }
104368
104391
  async function readManifest(path) {
104369
104392
  try {
@@ -104375,14 +104398,14 @@ async function readManifest(path) {
104375
104398
  async function findXctestrun(products) {
104376
104399
  const entries = await readdir2(products).catch(() => []);
104377
104400
  const name30 = entries.find((entry) => entry.endsWith(".xctestrun"));
104378
- return name30 ? join18(products, name30) : null;
104401
+ return name30 ? join16(products, name30) : null;
104379
104402
  }
104380
104403
  async function brandRunnerApp(products, exec) {
104381
- const platform = join18(products, "Debug-iphoneos");
104382
- const host = join18(platform, "YoqaRunner.app");
104383
- const runner = join18(platform, "YoqaRunnerUITests-Runner.app");
104384
- const staging = join18(products, "branding");
104385
- const copy = join18(staging, "YoqaRunnerUITests-Runner.app");
104404
+ const platform = join16(products, "Debug-iphoneos");
104405
+ const host = join16(platform, "YoqaRunner.app");
104406
+ const runner = join16(platform, "YoqaRunnerUITests-Runner.app");
104407
+ const staging = join16(products, "branding");
104408
+ const copy = join16(staging, "YoqaRunnerUITests-Runner.app");
104386
104409
  const run = async (command) => {
104387
104410
  const result = await exec(command);
104388
104411
  if (result.exitCode !== 0) {
@@ -104397,7 +104420,7 @@ async function brandRunnerApp(products, exec) {
104397
104420
  await rm7(staging, { recursive: true, force: true });
104398
104421
  await cp(runner, copy, { recursive: true, verbatimSymlinks: true });
104399
104422
  for (const name30 of icons)
104400
- await copyFile(join18(host, name30), join18(copy, name30));
104423
+ await copyFile(join16(host, name30), join16(copy, name30));
104401
104424
  const plist = await run([
104402
104425
  "plutil",
104403
104426
  "-extract",
@@ -104405,7 +104428,7 @@ async function brandRunnerApp(products, exec) {
104405
104428
  "json",
104406
104429
  "-o",
104407
104430
  "-",
104408
- join18(host, "Info.plist")
104431
+ join16(host, "Info.plist")
104409
104432
  ]);
104410
104433
  await run([
104411
104434
  "plutil",
@@ -104413,9 +104436,9 @@ async function brandRunnerApp(products, exec) {
104413
104436
  "CFBundleIcons",
104414
104437
  "-json",
104415
104438
  plist.trim(),
104416
- join18(copy, "Info.plist")
104439
+ join16(copy, "Info.plist")
104417
104440
  ]);
104418
- const certificates = join18(staging, "certificate");
104441
+ const certificates = join16(staging, "certificate");
104419
104442
  await run(["codesign", "-d", `--extract-certificates=${certificates}`, runner]);
104420
104443
  const identity2 = createHash("sha1").update(await readFile5(`${certificates}0`)).digest("hex").toUpperCase();
104421
104444
  await run([
@@ -104427,7 +104450,7 @@ async function brandRunnerApp(products, exec) {
104427
104450
  "--generate-entitlement-der",
104428
104451
  copy
104429
104452
  ]);
104430
- const unbranded = join18(staging, "unbranded.app");
104453
+ const unbranded = join16(staging, "unbranded.app");
104431
104454
  await rename(runner, unbranded);
104432
104455
  try {
104433
104456
  await rename(copy, runner);
@@ -104499,7 +104522,7 @@ function prepareYoqaRunner(udid, deps) {
104499
104522
  return next;
104500
104523
  }
104501
104524
  async function prepare(udid, deps) {
104502
- if (!existsSync5(join18(deps.projectDir, "YoqaRunner.xcodeproj"))) {
104525
+ if (!existsSync6(join16(deps.projectDir, "YoqaRunner.xcodeproj"))) {
104503
104526
  throw new YoqaRunnerError(`YoqaRunner's Xcode project is missing from this install (looked in ${deps.projectDir}). Reinstall yoqa, or set YOQA_RUNNER_PROJECT to a native/yoqa-runner checkout.`);
104504
104527
  }
104505
104528
  const team = await signingTeam(deps);
@@ -104508,8 +104531,8 @@ async function prepare(udid, deps) {
104508
104531
  deps.exec(["xcodebuild", "-version"])
104509
104532
  ]);
104510
104533
  const key = createHash("sha256").update(`${sources}\x00${xcodeVersion(xcode)}\x00${team}`).digest("hex").slice(0, 16);
104511
- const dir = join18(deps.cacheRoot, key);
104512
- const manifestPath = join18(dir, "build.json");
104534
+ const dir = join16(deps.cacheRoot, key);
104535
+ const manifestPath = join16(dir, "build.json");
104513
104536
  const cached2 = await readManifest(manifestPath);
104514
104537
  if (cached2 && usableFor(cached2, udid, deps.now())) {
104515
104538
  return {
@@ -104520,12 +104543,12 @@ async function prepare(udid, deps) {
104520
104543
  devices: cached2.devices
104521
104544
  };
104522
104545
  }
104523
- const derivedData = join18(dir, "DerivedData");
104546
+ const derivedData = join16(dir, "DerivedData");
104524
104547
  const build = await deps.exec([
104525
104548
  "xcodebuild",
104526
104549
  "build-for-testing",
104527
104550
  "-project",
104528
- join18(deps.projectDir, "YoqaRunner.xcodeproj"),
104551
+ join16(deps.projectDir, "YoqaRunner.xcodeproj"),
104529
104552
  "-scheme",
104530
104553
  "YoqaRunner",
104531
104554
  "-destination",
@@ -104542,7 +104565,7 @@ async function prepare(udid, deps) {
104542
104565
  throw new YoqaRunnerError(explainBuildFailure(`${build.stdout}
104543
104566
  ${build.stderr}`, team));
104544
104567
  }
104545
- const products = join18(derivedData, "Build/Products");
104568
+ const products = join16(derivedData, "Build/Products");
104546
104569
  const unbranded = await brandRunnerApp(products, deps.exec);
104547
104570
  if (unbranded)
104548
104571
  console.warn(`[yoqa-runner] the runner keeps Xcode's blank icon: ${unbranded}`);
@@ -104697,13 +104720,13 @@ function resolveYoqaRunnerProject(at) {
104697
104720
  const fromEnv = at.env.YOQA_RUNNER_PROJECT?.trim();
104698
104721
  if (fromEnv)
104699
104722
  return fromEnv;
104700
- if (existsSync5(join18(at.checkout, "YoqaRunner.xcodeproj")))
104723
+ if (existsSync6(join16(at.checkout, "YoqaRunner.xcodeproj")))
104701
104724
  return at.checkout;
104702
- if (!existsSync5(at.archive))
104725
+ if (!existsSync6(at.archive))
104703
104726
  return at.checkout;
104704
104727
  const key = createHash("sha256").update(readFileSync(at.archive)).digest("hex").slice(0, 16);
104705
- const dir = join18(at.cacheRoot, "source", key);
104706
- if (existsSync5(join18(dir, "YoqaRunner.xcodeproj")))
104728
+ const dir = join16(at.cacheRoot, "source", key);
104729
+ if (existsSync6(join16(dir, "YoqaRunner.xcodeproj")))
104707
104730
  return dir;
104708
104731
  const staging = `${dir}.${process.pid}.tmp`;
104709
104732
  rmSync(staging, { recursive: true, force: true });
@@ -104721,7 +104744,7 @@ function resolveYoqaRunnerProject(at) {
104721
104744
  return dir;
104722
104745
  }
104723
104746
  function yoqaRunnerDeps() {
104724
- const cacheRoot = join18(homedir10(), ".yoqa", "yoqa-runner");
104747
+ const cacheRoot = join16(homedir10(), ".yoqa", "yoqa-runner");
104725
104748
  return {
104726
104749
  exec: execCommand,
104727
104750
  spawn: (command, env) => Bun.spawn(command, {
@@ -104733,12 +104756,12 @@ function yoqaRunnerDeps() {
104733
104756
  env: process.env,
104734
104757
  projectDir: resolveYoqaRunnerProject({
104735
104758
  env: process.env,
104736
- checkout: join18(import.meta.dir, "../../../../../native/yoqa-runner"),
104737
- archive: join18(dirname5(process.execPath), RUNNER_SOURCE_ARCHIVE),
104759
+ checkout: join16(import.meta.dir, "../../../../../native/yoqa-runner"),
104760
+ archive: join16(dirname5(process.execPath), RUNNER_SOURCE_ARCHIVE),
104738
104761
  cacheRoot
104739
104762
  }),
104740
104763
  cacheRoot,
104741
- settingsPath: join18(homedir10(), ".yoqa", "ios-signing.json"),
104764
+ settingsPath: join16(homedir10(), ".yoqa", "ios-signing.json"),
104742
104765
  now: () => new Date
104743
104766
  };
104744
104767
  }
@@ -104982,7 +105005,7 @@ async function createIosDeviceSession(options, deps = iosDeviceDeps()) {
104982
105005
  const screenshot = async () => {
104983
105006
  await mkdir5(SCREENSHOT_DIR, { recursive: true });
104984
105007
  const frame = await captureFrame();
104985
- const path = join19(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
105008
+ const path = join17(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
104986
105009
  await Bun.write(path, Uint8Array.from(Buffer.from(frame.base64, "base64")));
104987
105010
  return { path, base64: frame.base64 };
104988
105011
  };
@@ -105117,7 +105140,7 @@ function directOptIn(deviceClass, env = process.env) {
105117
105140
 
105118
105141
  // src/domains/devices/web-direct-lane.ts
105119
105142
  import { mkdir as mkdir6 } from "fs/promises";
105120
- import { join as join20 } from "path";
105143
+ import { join as join18 } from "path";
105121
105144
 
105122
105145
  // src/domains/devices/cdp-client.ts
105123
105146
  class CdpClosedError extends Error {
@@ -105659,7 +105682,7 @@ async function createWebDirectSession(options, deps = webDirectDeps()) {
105659
105682
  const screenshot = async () => {
105660
105683
  await mkdir6(SCREENSHOT_DIR, { recursive: true });
105661
105684
  const frame = await captureFrame();
105662
- const path = join20(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
105685
+ const path = join18(SCREENSHOT_DIR, `shot_${Date.now()}_${crypto.randomUUID()}.png`);
105663
105686
  await Bun.write(path, Uint8Array.from(Buffer.from(frame.base64, "base64")));
105664
105687
  return { path, base64: frame.base64 };
105665
105688
  };
@@ -105740,9 +105763,9 @@ async function createWebDirectSession(options, deps = webDirectDeps()) {
105740
105763
 
105741
105764
  // src/domains/devices/yoqa-ax.ts
105742
105765
  import { randomBytes } from "crypto";
105743
- import { existsSync as existsSync6, rmSync as rmSync2 } from "fs";
105766
+ import { existsSync as existsSync7, rmSync as rmSync2 } from "fs";
105744
105767
  import { createServer } from "net";
105745
- import { join as join21 } from "path";
105768
+ import { join as join19 } from "path";
105746
105769
  var CONNECT_TIMEOUT_MS2 = 1e4;
105747
105770
  var REQUEST_TIMEOUT_MS2 = 5000;
105748
105771
  var STOP_GRACE_MS3 = 2000;
@@ -105753,10 +105776,10 @@ function resolveYoqaAxBin() {
105753
105776
  const fromEnv = process.env.YOQA_AX_BIN?.trim();
105754
105777
  if (fromEnv)
105755
105778
  return fromEnv;
105756
- const products = join21(import.meta.dir, "../../../../../native/yoqa-ax/.build/out/Products");
105779
+ const products = join19(import.meta.dir, "../../../../../native/yoqa-ax/.build/out/Products");
105757
105780
  for (const config2 of ["Release-iphonesimulator", "Debug-iphonesimulator"]) {
105758
- const built = join21(products, config2, "yoqa-ax");
105759
- if (existsSync6(built))
105781
+ const built = join19(products, config2, "yoqa-ax");
105782
+ if (existsSync7(built))
105760
105783
  return built;
105761
105784
  }
105762
105785
  return null;
@@ -106282,11 +106305,11 @@ import {
106282
106305
  createDecipheriv,
106283
106306
  randomBytes as randomBytes2
106284
106307
  } from "crypto";
106285
- import { chmodSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
106308
+ import { chmodSync, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
106286
106309
  import { homedir as homedir11 } from "os";
106287
- import { dirname as dirname6, join as join22 } from "path";
106288
- var YOQA_ROOT2 = join22(homedir11(), ".yoqa");
106289
- var KEY_PATH = join22(YOQA_ROOT2, ".provider-key");
106310
+ import { dirname as dirname6, join as join20 } from "path";
106311
+ var YOQA_ROOT2 = join20(homedir11(), ".yoqa");
106312
+ var KEY_PATH = join20(YOQA_ROOT2, ".provider-key");
106290
106313
  var ALGORITHM = "aes-256-gcm";
106291
106314
  var IV_LENGTH = 12;
106292
106315
  var KEY_LENGTH = 32;
@@ -106320,7 +106343,7 @@ function base64ToBytes(value) {
106320
106343
  }
106321
106344
  function ensureProviderKey() {
106322
106345
  mkdirSync3(YOQA_ROOT2, { recursive: true });
106323
- if (existsSync7(KEY_PATH)) {
106346
+ if (existsSync8(KEY_PATH)) {
106324
106347
  const existing = toBytes(readFileSync2(KEY_PATH));
106325
106348
  if (existing.length === KEY_LENGTH) {
106326
106349
  return existing;
@@ -107975,13 +107998,13 @@ function reportedLaneWarning(warning) {
107975
107998
  }
107976
107999
 
107977
108000
  // src/domains/runs/run-recording.ts
107978
- import { existsSync as existsSync8 } from "fs";
108001
+ import { existsSync as existsSync9 } from "fs";
107979
108002
  import { rm as rm8 } from "fs/promises";
107980
108003
  import { homedir as homedir12 } from "os";
107981
- import { join as join23 } from "path";
107982
- var RUN_VIDEO_DIR = join23(homedir12(), ".yoqa", "runs", "videos");
108004
+ import { join as join21 } from "path";
108005
+ var RUN_VIDEO_DIR = join21(homedir12(), ".yoqa", "runs", "videos");
107983
108006
  function runVideoPath(runTestId, dir = RUN_VIDEO_DIR) {
107984
- return join23(dir, `${runTestId}.mp4`);
108007
+ return join21(dir, `${runTestId}.mp4`);
107985
108008
  }
107986
108009
  var STOP_TIMEOUT_MS = 20000;
107987
108010
  function errorMessage7(error40) {
@@ -108017,7 +108040,7 @@ async function startRunRecording(session, path) {
108017
108040
  } catch (error40) {
108018
108041
  return { status: "unavailable", note: `Could not save recording: ${errorMessage7(error40)}` };
108019
108042
  }
108020
- if (!existsSync8(path)) {
108043
+ if (!existsSync9(path)) {
108021
108044
  return { status: "unavailable", note: "The device produced no video file" };
108022
108045
  }
108023
108046
  return { status: "ready" };
@@ -108031,7 +108054,7 @@ async function deleteRunVideo(runTestId, dir = RUN_VIDEO_DIR) {
108031
108054
  }
108032
108055
  function readyVideoPath(runTestId, status, dir = RUN_VIDEO_DIR) {
108033
108056
  const path = runVideoPath(runTestId, dir);
108034
- return status === "ready" && existsSync8(path) ? path : null;
108057
+ return status === "ready" && existsSync9(path) ? path : null;
108035
108058
  }
108036
108059
  async function recordCase(session, path, options, run) {
108037
108060
  if (!options.enabled)
@@ -108717,7 +108740,7 @@ async function getRunStepScreenshotPath(runId, stepId) {
108717
108740
  const step = test.steps?.find((item) => item.id === stepId);
108718
108741
  if (!step)
108719
108742
  continue;
108720
- if (!step.screenshotUri || !existsSync9(step.screenshotUri)) {
108743
+ if (!step.screenshotUri || !existsSync10(step.screenshotUri)) {
108721
108744
  throw new RunNotFoundError("Screenshot not found");
108722
108745
  }
108723
108746
  return step.screenshotUri;
@@ -110730,12 +110753,11 @@ function createDevicesRoutes() {
110730
110753
  }
110731
110754
 
110732
110755
  // src/domains/doctor/application.ts
110733
- import { homedir as homedir13 } from "os";
110734
- import { join as join24 } from "path";
110756
+ import { join as join22 } from "path";
110735
110757
  // package.json
110736
110758
  var package_default = {
110737
110759
  name: "@yoqa/runner",
110738
- version: "1.0.4",
110760
+ version: "1.0.5",
110739
110761
  description: "Yoqa local runner \u2014 device control + catalog HTTP API (Bun). Start with yoqa serve or the yoqa-runner bin.",
110740
110762
  license: "UNLICENSED",
110741
110763
  type: "module",
@@ -110920,12 +110942,8 @@ async function runCommand3(command, options) {
110920
110942
  }
110921
110943
  }
110922
110944
  async function which2(bin) {
110923
- const { stdout, exitCode } = await runCommand3(["which", bin]);
110924
- if (exitCode !== 0)
110925
- return null;
110926
- const path = stdout.trim().split(`
110927
- `)[0]?.trim();
110928
- return path || null;
110945
+ ensureHostToolPath();
110946
+ return Bun.which(bin);
110929
110947
  }
110930
110948
  async function probeJava() {
110931
110949
  const javaHome = process.env.JAVA_HOME;
@@ -110934,7 +110952,7 @@ async function probeJava() {
110934
110952
  let detail = javaBin ?? "java not on PATH";
110935
110953
  if (javaHome)
110936
110954
  detail = `JAVA_HOME=${javaHome}`;
110937
- else if (await Bun.file(join24(studioJbr, "bin/java")).exists()) {
110955
+ else if (await Bun.file(join22(studioJbr, "bin/java")).exists()) {
110938
110956
  detail = `Android Studio JBR available at ${studioJbr} (JAVA_HOME unset)`;
110939
110957
  }
110940
110958
  const ok = Boolean(javaBin || javaHome);
@@ -110965,8 +110983,9 @@ async function probeXcodeSelect() {
110965
110983
  };
110966
110984
  }
110967
110985
  async function probeAdbDevices() {
110968
- const adb = await which2("adb") ?? join24(homedir13(), "Library/Android/sdk/platform-tools/adb");
110969
- if (!await Bun.file(adb).exists() && !await which2("adb")) {
110986
+ const sdk = resolveAndroidSdkRoot();
110987
+ const adb = await which2("adb") ?? (sdk ? androidSdkToolPath(sdk, "platform-tools", "adb") : null);
110988
+ if (!adb || !await Bun.file(adb).exists()) {
110970
110989
  return {
110971
110990
  id: "adb-devices",
110972
110991
  label: "ADB devices",
@@ -111604,12 +111623,12 @@ import { dirname as dirname7 } from "path";
111604
111623
 
111605
111624
  // src/domains/devices/action-result.ts
111606
111625
  import { mkdir as mkdir7 } from "fs/promises";
111607
- import { join as join26 } from "path";
111626
+ import { join as join24 } from "path";
111608
111627
 
111609
111628
  // src/domains/devices/agent-image.ts
111610
111629
  import { mkdtemp as mkdtemp7, readFile as readFile7, rm as rm9, writeFile as writeFile5 } from "fs/promises";
111611
111630
  import { tmpdir as tmpdir8 } from "os";
111612
- import { join as join25 } from "path";
111631
+ import { join as join23 } from "path";
111613
111632
  var DEFAULT_AGENT_IMAGE_EDGE = 1000;
111614
111633
  function targetEdge(pngBase64, options) {
111615
111634
  if (options.full || options.scale === 1)
@@ -111628,9 +111647,9 @@ async function prepareAgentImage(pngBase64, options = {}) {
111628
111647
  if (bytes.byteLength === 0 || edge == null || process.platform !== "darwin") {
111629
111648
  return { base64: pngBase64, mediaType: "image/png", downscaled: false };
111630
111649
  }
111631
- const dir = await mkdtemp7(join25(tmpdir8(), "yoqa-agent-image-"));
111632
- const inPath = join25(dir, "shot.png");
111633
- const outPath = join25(dir, "shot.jpg");
111650
+ const dir = await mkdtemp7(join23(tmpdir8(), "yoqa-agent-image-"));
111651
+ const inPath = join23(dir, "shot.png");
111652
+ const outPath = join23(dir, "shot.jpg");
111634
111653
  try {
111635
111654
  await writeFile5(inPath, new Uint8Array(bytes));
111636
111655
  const proc = Bun.spawn([
@@ -111720,7 +111739,7 @@ function actionMarks(body, resolved) {
111720
111739
  }
111721
111740
  async function writeImage(dir, base643, label, ext) {
111722
111741
  await mkdir7(dir, { recursive: true });
111723
- const path = join26(dir, `${label}_${Date.now()}_${crypto.randomUUID()}.${ext}`);
111742
+ const path = join24(dir, `${label}_${Date.now()}_${crypto.randomUUID()}.${ext}`);
111724
111743
  await Bun.write(path, Uint8Array.from(Buffer.from(base643, "base64")));
111725
111744
  return path;
111726
111745
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoqa/runner",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Yoqa local runner — device control + catalog HTTP API (Bun). Start with yoqa serve or the yoqa-runner bin.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",