@axlsdk/studio 0.16.1 → 0.17.1

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.
@@ -34,9 +34,9 @@ __export(middleware_exports, {
34
34
  handleWsMessage: () => handleWsMessage
35
35
  });
36
36
  module.exports = __toCommonJS(middleware_exports);
37
- var import_node_path4 = require("path");
38
- var import_node_fs4 = require("fs");
39
- var import_node_url3 = require("url");
37
+ var import_node_path3 = require("path");
38
+ var import_node_fs2 = require("fs");
39
+ var import_node_url2 = require("url");
40
40
  var import_node_server = require("@hono/node-server");
41
41
  var import_ws = require("ws");
42
42
 
@@ -142,8 +142,11 @@ function redactEvalItem(item) {
142
142
  }
143
143
  function redactEvalResult(result, redact) {
144
144
  if (!redact) return result;
145
+ const meta = result.metadata;
146
+ const scrubbedMetadata = meta && typeof meta.batchFailure === "string" ? { ...meta, batchFailure: REDACTED } : result.metadata;
145
147
  return {
146
148
  ...result,
149
+ metadata: scrubbedMetadata,
147
150
  items: result.items.map(redactEvalItem)
148
151
  };
149
152
  }
@@ -938,13 +941,18 @@ function reduceEvalTrends(acc, entry) {
938
941
  const cost = extractCost(entry.data);
939
942
  const model = extractModel(entry.data);
940
943
  const duration = extractDuration(entry.data);
944
+ const metadata = entry.data?.metadata;
945
+ const runGroupId = typeof metadata?.runGroupId === "string" ? metadata.runGroupId : void 0;
946
+ const batchAttempted = typeof metadata?.batchAttempted === "number" && Number.isFinite(metadata.batchAttempted) ? metadata.batchAttempted : void 0;
941
947
  const run = {
942
948
  timestamp: entry.timestamp,
943
949
  id: entry.id,
944
950
  scores,
945
951
  cost,
946
952
  ...model !== void 0 ? { model } : {},
947
- ...duration !== void 0 ? { duration } : {}
953
+ ...duration !== void 0 ? { duration } : {},
954
+ ...runGroupId !== void 0 ? { runGroupId } : {},
955
+ ...batchAttempted !== void 0 ? { batchAttempted } : {}
948
956
  };
949
957
  const byEval = { ...acc.byEval };
950
958
  const prev = byEval[entry.eval];
@@ -1627,33 +1635,79 @@ function createEvalRoutes(connMgr, evalLoader) {
1627
1635
  if (runs > 1) {
1628
1636
  const runGroupId = (0, import_node_crypto.randomUUID)();
1629
1637
  const results = [];
1638
+ let runFailure;
1639
+ let cancelled = false;
1630
1640
  for (let r = 0; r < runs; r++) {
1631
- if (ac.signal.aborted) break;
1632
- const result = await runtime.runRegisteredEval(name, {
1633
- metadata: { runGroupId, runIndex: r },
1634
- signal: ac.signal,
1635
- captureTraces,
1636
- onProgress: (event) => {
1637
- if (event.type === "run_done") return;
1641
+ if (ac.signal.aborted) {
1642
+ cancelled = true;
1643
+ break;
1644
+ }
1645
+ try {
1646
+ const result = await runtime.runRegisteredEval(name, {
1647
+ metadata: { runGroupId, runIndex: r, batchAttempted: runs },
1648
+ signal: ac.signal,
1649
+ captureTraces,
1650
+ onProgress: (event) => {
1651
+ if (event.type === "run_done") return;
1652
+ connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1653
+ ...event,
1654
+ run: r + 1,
1655
+ totalRuns: runs
1656
+ });
1657
+ }
1658
+ });
1659
+ results.push(result);
1660
+ connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1661
+ type: "run_done",
1662
+ run: r + 1,
1663
+ totalRuns: runs
1664
+ });
1665
+ } catch (err) {
1666
+ const isAbort = ac.signal.aborted || err instanceof Error && err.name === "AbortError";
1667
+ if (isAbort) {
1668
+ cancelled = true;
1638
1669
  connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1639
- ...event,
1670
+ type: "run_cancelled",
1640
1671
  run: r + 1,
1641
1672
  totalRuns: runs
1642
1673
  });
1674
+ break;
1643
1675
  }
1644
- });
1645
- results.push(result);
1646
- connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1647
- type: "run_done",
1648
- run: r + 1,
1649
- totalRuns: runs
1650
- });
1676
+ runFailure = err instanceof Error ? err : new Error(String(err));
1677
+ connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1678
+ type: "run_failed",
1679
+ run: r + 1,
1680
+ totalRuns: runs,
1681
+ message: redactErrorMessage(runFailure, redactOn)
1682
+ });
1683
+ break;
1684
+ }
1651
1685
  }
1652
1686
  if (results.length > 0) {
1687
+ const partial = results.length < runs;
1688
+ const failureMsg = runFailure ? redactErrorMessage(runFailure, redactOn) || String(runFailure) || void 0 : void 0;
1653
1689
  connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1654
1690
  type: "done",
1655
1691
  evalResultId: results[0].id,
1656
- runGroupId
1692
+ runGroupId,
1693
+ ...partial && {
1694
+ partial: true,
1695
+ batchCompleted: results.length,
1696
+ batchAttempted: runs,
1697
+ // `cancelled` and `batchFailure` are mutually exclusive:
1698
+ // the catch block sets at most one of {cancelled,
1699
+ // runFailure}. The client uses `cancelled` to render a
1700
+ // neutral "Cancelled — X of N runs completed" caption
1701
+ // instead of the amber "Stopped after: <message>"
1702
+ // failure caption.
1703
+ ...cancelled ? { cancelled: true } : {},
1704
+ ...failureMsg ? { batchFailure: failureMsg } : {}
1705
+ }
1706
+ });
1707
+ } else if (runFailure) {
1708
+ connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
1709
+ type: "error",
1710
+ message: redactErrorMessage(runFailure, redactOn)
1657
1711
  });
1658
1712
  } else {
1659
1713
  connMgr.broadcastWithWildcard(`eval:${evalRunId}`, {
@@ -1691,19 +1745,38 @@ function createEvalRoutes(connMgr, evalLoader) {
1691
1745
  const { aggregateRuns } = await import("@axlsdk/eval");
1692
1746
  const runGroupId = (0, import_node_crypto.randomUUID)();
1693
1747
  const results = [];
1748
+ let runFailure;
1694
1749
  for (let r = 0; r < runs; r++) {
1695
- const result2 = await runtime.runRegisteredEval(name, {
1696
- metadata: { runGroupId, runIndex: r },
1697
- captureTraces
1698
- });
1699
- results.push(result2);
1750
+ try {
1751
+ const result2 = await runtime.runRegisteredEval(name, {
1752
+ metadata: { runGroupId, runIndex: r, batchAttempted: runs },
1753
+ captureTraces
1754
+ });
1755
+ results.push(result2);
1756
+ } catch (err) {
1757
+ runFailure = err instanceof Error ? err : new Error(String(err));
1758
+ break;
1759
+ }
1760
+ }
1761
+ if (results.length === 0) {
1762
+ throw runFailure ?? new Error("No runs completed");
1700
1763
  }
1701
- const typedResults = results;
1702
- const aggregate = aggregateRuns(typedResults);
1703
- const first = typedResults[0];
1764
+ const aggregate = aggregateRuns(results);
1765
+ const first = results[0];
1766
+ const partial = results.length < runs;
1767
+ const failureMsg = runFailure ? redactErrorMessage(runFailure, redactOn) || String(runFailure) || void 0 : void 0;
1704
1768
  const result = {
1705
1769
  ...first,
1706
- _multiRun: { aggregate, allRuns: typedResults }
1770
+ _multiRun: {
1771
+ aggregate,
1772
+ allRuns: results,
1773
+ ...partial && {
1774
+ partial: true,
1775
+ batchCompleted: results.length,
1776
+ batchAttempted: runs,
1777
+ ...failureMsg ? { batchFailure: failureMsg } : {}
1778
+ }
1779
+ }
1707
1780
  };
1708
1781
  return c.json({
1709
1782
  ok: true,
@@ -1875,60 +1948,75 @@ function createEvalRoutes(connMgr, evalLoader) {
1875
1948
  const runtime = c.get("runtime");
1876
1949
  const body = await c.req.json();
1877
1950
  const bad = (message) => c.json({ ok: false, error: { code: "BAD_REQUEST", message } }, 400);
1878
- if (!body.result || typeof body.result !== "object") {
1951
+ if (body.result === void 0 || body.result === null) {
1879
1952
  return bad("result is required");
1880
1953
  }
1881
- const result = body.result;
1882
- if (!Array.isArray(result.items)) {
1883
- return bad("result.items must be an array");
1884
- }
1885
- if (typeof result.summary !== "object" || result.summary == null) {
1886
- return bad("result.summary must be an object");
1887
- }
1888
- if (typeof result.dataset !== "string" || !result.dataset) {
1889
- return bad("result.dataset must be a non-empty string (required for compare)");
1890
- }
1891
- const summary = result.summary;
1892
- if (typeof summary.scorers !== "object" || summary.scorers == null) {
1893
- return bad("result.summary.scorers must be an object");
1894
- }
1895
- const summaryScorerNames = Object.keys(summary.scorers);
1896
- const items = result.items;
1897
- const summaryScorerSet = new Set(summaryScorerNames);
1898
- const uncoveredAcrossItems = /* @__PURE__ */ new Set();
1899
- for (const item of items) {
1900
- const itemScores = item?.scores;
1901
- if (itemScores && typeof itemScores === "object") {
1902
- for (const name of Object.keys(itemScores)) {
1903
- if (!summaryScorerSet.has(name)) uncoveredAcrossItems.add(name);
1954
+ const resultsRaw = Array.isArray(body.result) ? body.result : [body.result];
1955
+ if (resultsRaw.length === 0) {
1956
+ return bad("result must be a non-empty array or object");
1957
+ }
1958
+ const validatedResults = [];
1959
+ for (let i = 0; i < resultsRaw.length; i++) {
1960
+ const entry = resultsRaw[i];
1961
+ const prefix = resultsRaw.length > 1 ? `result[${i}]` : "result";
1962
+ if (!entry || typeof entry !== "object") {
1963
+ return bad(`${prefix} must be an object`);
1964
+ }
1965
+ const r = entry;
1966
+ if (!Array.isArray(r.items)) {
1967
+ return bad(`${prefix}.items must be an array`);
1968
+ }
1969
+ if (typeof r.summary !== "object" || r.summary == null) {
1970
+ return bad(`${prefix}.summary must be an object`);
1971
+ }
1972
+ if (typeof r.dataset !== "string" || !r.dataset) {
1973
+ return bad(`${prefix}.dataset must be a non-empty string (required for compare)`);
1974
+ }
1975
+ const summary = r.summary;
1976
+ if (typeof summary.scorers !== "object" || summary.scorers == null) {
1977
+ return bad(`${prefix}.summary.scorers must be an object`);
1978
+ }
1979
+ const summaryScorerNames = Object.keys(summary.scorers);
1980
+ const items = r.items;
1981
+ const summaryScorerSet = new Set(summaryScorerNames);
1982
+ const uncoveredAcrossItems = /* @__PURE__ */ new Set();
1983
+ for (const item of items) {
1984
+ const itemScores = item?.scores;
1985
+ if (itemScores && typeof itemScores === "object") {
1986
+ for (const name of Object.keys(itemScores)) {
1987
+ if (!summaryScorerSet.has(name)) uncoveredAcrossItems.add(name);
1988
+ }
1904
1989
  }
1905
1990
  }
1906
- }
1907
- if (uncoveredAcrossItems.size > 0) {
1908
- return bad(
1909
- `item scores reference scorer(s) not in summary.scorers: ${[...uncoveredAcrossItems].join(", ")}`
1910
- );
1991
+ if (uncoveredAcrossItems.size > 0) {
1992
+ return bad(
1993
+ `${prefix} item scores reference scorer(s) not in summary.scorers: ${[...uncoveredAcrossItems].join(", ")}`
1994
+ );
1995
+ }
1996
+ validatedResults.push(r);
1911
1997
  }
1912
1998
  const trim = (v) => typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
1913
- const metadataObj = typeof result.metadata === "object" && result.metadata != null ? result.metadata : {};
1999
+ const firstResult = validatedResults[0];
2000
+ const metadataObj = typeof firstResult.metadata === "object" && firstResult.metadata != null ? firstResult.metadata : {};
1914
2001
  const workflowsFromMeta = Array.isArray(metadataObj.workflows) ? metadataObj.workflows : [];
1915
2002
  const primaryWorkflow = workflowsFromMeta.find((w) => typeof w === "string");
1916
- const evalName = trim(body.eval) ?? trim(primaryWorkflow) ?? // Legacy fallback: pre-0.14 CLI artifacts had workflow at the top level.
1917
- trim(result.workflow) ?? "imported";
1918
- const id = (0, import_node_crypto.randomUUID)();
2003
+ const evalName = trim(body.eval) ?? trim(primaryWorkflow) ?? trim(firstResult.workflow) ?? "imported";
1919
2004
  const timestamp = Date.now();
1920
- const imported = {
1921
- ...result,
1922
- id,
1923
- metadata: typeof result.metadata === "object" && result.metadata != null ? result.metadata : {}
1924
- };
1925
- await runtime.saveEvalResult({
1926
- id,
1927
- eval: evalName,
1928
- timestamp,
1929
- data: imported
1930
- });
1931
- return c.json({ ok: true, data: { id, eval: evalName, timestamp } });
2005
+ const imported = [];
2006
+ for (const r of validatedResults) {
2007
+ const id = (0, import_node_crypto.randomUUID)();
2008
+ const entry = {
2009
+ ...r,
2010
+ id,
2011
+ metadata: typeof r.metadata === "object" && r.metadata != null ? r.metadata : {}
2012
+ };
2013
+ await runtime.saveEvalResult({ id, eval: evalName, timestamp, data: entry });
2014
+ imported.push({ id, eval: evalName, timestamp });
2015
+ }
2016
+ if (imported.length === 1) {
2017
+ return c.json({ ok: true, data: imported[0] });
2018
+ }
2019
+ return c.json({ ok: true, data: { imported } });
1932
2020
  });
1933
2021
  function closeActiveRuns() {
1934
2022
  for (const ac of activeRuns.values()) ac.abort();
@@ -2245,41 +2333,11 @@ function createServer(options) {
2245
2333
  }
2246
2334
 
2247
2335
  // src/eval-loader.ts
2248
- var import_node_path3 = require("path");
2249
- var import_node_fs3 = require("fs");
2250
- var import_node_url2 = require("url");
2251
-
2252
- // src/cli-utils.ts
2253
2336
  var import_node_path2 = require("path");
2254
- var import_node_fs2 = require("fs");
2255
2337
  var import_node_url = require("url");
2256
- function needsTsxLoader(configPath) {
2257
- return /\.[mc]?tsx?$/.test(configPath);
2258
- }
2259
- var tsImportFn;
2260
- async function importModule(filePath, parentURL2) {
2261
- if (needsTsxLoader(filePath)) {
2262
- if (tsImportFn === void 0) {
2263
- try {
2264
- const mod = await import("tsx/esm/api");
2265
- tsImportFn = mod.tsImport ?? null;
2266
- } catch {
2267
- tsImportFn = null;
2268
- console.warn(
2269
- "[axl-studio] Warning: tsx is not installed. TypeScript config files require tsx as a dependency.\n Install it with: npm install -D tsx"
2270
- );
2271
- }
2272
- }
2273
- if (tsImportFn) {
2274
- return await tsImportFn((0, import_node_url.pathToFileURL)(filePath).href, parentURL2);
2275
- }
2276
- }
2277
- return await import((0, import_node_url.pathToFileURL)(filePath).href);
2278
- }
2279
-
2280
- // src/eval-loader.ts
2338
+ var import_axl6 = require("@axlsdk/axl");
2281
2339
  var import_meta = {};
2282
- var parentURL = import_meta.url ?? (0, import_node_url2.pathToFileURL)(typeof __filename !== "undefined" ? __filename : __dirname).href;
2340
+ var parentURL = import_meta.url ?? (0, import_node_url.pathToFileURL)(typeof __filename !== "undefined" ? __filename : __dirname).href;
2283
2341
  function createEvalLoader(config, runtime, cwd) {
2284
2342
  let loadPromise;
2285
2343
  const { patterns, conditions } = normalizeConfig(config);
@@ -2296,7 +2354,7 @@ function createEvalLoader(config, runtime, cwd) {
2296
2354
  }
2297
2355
  async function loadEvalFiles(patterns, conditions, cwd, runtime) {
2298
2356
  if (conditions.length > 0) {
2299
- await registerConditions(conditions);
2357
+ await (0, import_axl6.registerConditions)(conditions);
2300
2358
  }
2301
2359
  const files = resolvePatterns(patterns, cwd);
2302
2360
  if (files.length === 0) {
@@ -2305,11 +2363,30 @@ async function loadEvalFiles(patterns, conditions, cwd, runtime) {
2305
2363
  }
2306
2364
  for (const file of files) {
2307
2365
  try {
2308
- const mod = await importModule(file, parentURL);
2309
- const evalConfig = mod.default?.default ?? mod.default ?? mod.config ?? mod;
2366
+ const mod = await (0, import_axl6.importModule)(file, parentURL);
2367
+ const evalConfig = (0, import_axl6.pickDefault)(mod);
2368
+ if (!evalConfig || typeof evalConfig !== "object") {
2369
+ console.warn(
2370
+ `[axl-studio] Skipping ${file}: default export is ${evalConfig === null ? "null" : typeof evalConfig}, expected an eval config object.`
2371
+ );
2372
+ continue;
2373
+ }
2374
+ if (Array.isArray(evalConfig.scorers) && evalConfig.scorers.length === 0) {
2375
+ console.warn(
2376
+ `[axl-studio] Skipping ${file}: scorers array is empty \u2014 at least one scorer is required.`
2377
+ );
2378
+ continue;
2379
+ }
2310
2380
  if (!evalConfig.workflow || !evalConfig.dataset || !evalConfig.scorers) {
2381
+ const missing = [
2382
+ !evalConfig.workflow && "workflow",
2383
+ !evalConfig.dataset && "dataset",
2384
+ !evalConfig.scorers && "scorers"
2385
+ ].filter(Boolean).join(", ");
2386
+ const keys = Object.keys(evalConfig).slice(0, 10);
2387
+ const got = keys.length > 0 ? ` Got: { ${keys.join(", ")} }.` : "";
2311
2388
  console.warn(
2312
- `[axl-studio] Skipping ${file}: not a valid eval config (missing workflow, dataset, or scorers)`
2389
+ `[axl-studio] Skipping ${file}: not a valid eval config (missing ${missing}).${got}`
2313
2390
  );
2314
2391
  continue;
2315
2392
  }
@@ -2319,7 +2396,16 @@ async function loadEvalFiles(patterns, conditions, cwd, runtime) {
2319
2396
  `[axl-studio] Eval name "${name}" from ${file} collides with an already-registered eval \u2014 overwriting`
2320
2397
  );
2321
2398
  }
2322
- runtime.registerEval(name, evalConfig, mod.executeWorkflow);
2399
+ const exported = (0, import_axl6.pickExport)(mod, "executeWorkflow");
2400
+ let customExecute;
2401
+ if (typeof exported === "function") {
2402
+ customExecute = exported;
2403
+ } else if (exported !== void 0) {
2404
+ console.warn(
2405
+ `[axl-studio] ${file} exports executeWorkflow but it is ${typeof exported}, not a function \u2014 ignoring and falling back to runtime.execute()`
2406
+ );
2407
+ }
2408
+ runtime.registerEval(name, evalConfig, customExecute);
2323
2409
  } catch (err) {
2324
2410
  const msg = err instanceof Error ? err.message : String(err);
2325
2411
  console.warn(`[axl-studio] Failed to load eval ${file}: ${msg}`);
@@ -2337,10 +2423,10 @@ function normalizeConfig(config) {
2337
2423
  return { patterns: files, conditions: config.conditions ?? [] };
2338
2424
  }
2339
2425
  function deriveEvalName(filePath, cwd) {
2340
- const rel = (0, import_node_path3.relative)(cwd, filePath);
2426
+ const rel = (0, import_node_path2.relative)(cwd, filePath);
2341
2427
  const normalized = rel.replace(/\\/g, "/");
2342
2428
  if (normalized.startsWith("../")) {
2343
- const base = (0, import_node_path3.basename)(filePath);
2429
+ const base = (0, import_node_path2.basename)(filePath);
2344
2430
  const stripped = base.replace(/\.eval\.[mc]?[jt]sx?$/, "");
2345
2431
  return stripped !== base ? stripped : base.replace(/\.[mc]?[jt]sx?$/, "") || base;
2346
2432
  }
@@ -2353,7 +2439,7 @@ function resolvePatterns(patterns, cwd) {
2353
2439
  const files = [];
2354
2440
  const seen = /* @__PURE__ */ new Set();
2355
2441
  for (const pattern of patterns) {
2356
- const resolved = pattern.includes("*") ? expandGlob(pattern, cwd) : [(0, import_node_path3.resolve)(cwd, pattern)];
2442
+ const resolved = pattern.includes("*") ? (0, import_axl6.expandGlob)(pattern, cwd) : [(0, import_node_path2.resolve)(cwd, pattern)];
2357
2443
  for (const file of resolved) {
2358
2444
  if (!seen.has(file)) {
2359
2445
  seen.add(file);
@@ -2363,61 +2449,6 @@ function resolvePatterns(patterns, cwd) {
2363
2449
  }
2364
2450
  return files;
2365
2451
  }
2366
- function expandGlob(pattern, cwd) {
2367
- if (pattern.includes("**/")) {
2368
- const sepIdx = pattern.indexOf("**/");
2369
- const baseDir = (0, import_node_path3.resolve)(cwd, pattern.slice(0, sepIdx) || ".");
2370
- const fileGlob2 = pattern.slice(sepIdx + 3) || "*";
2371
- return findFiles(baseDir, fileGlob2, true);
2372
- }
2373
- const dir = (0, import_node_path3.resolve)(cwd, (0, import_node_path3.dirname)(pattern));
2374
- const fileGlob = (0, import_node_path3.basename)(pattern);
2375
- return findFiles(dir, fileGlob, false);
2376
- }
2377
- var MAX_DEPTH = 20;
2378
- function findFiles(dir, fileGlob, recursive, depth = 0) {
2379
- if (depth > MAX_DEPTH) return [];
2380
- const matcher = globToRegex(fileGlob);
2381
- const results = [];
2382
- try {
2383
- const entries = (0, import_node_fs3.readdirSync)(dir);
2384
- for (const entry of entries) {
2385
- const full = (0, import_node_path3.resolve)(dir, entry);
2386
- try {
2387
- const stat = (0, import_node_fs3.statSync)(full);
2388
- if (stat.isFile() && matcher.test(entry)) {
2389
- results.push(full);
2390
- } else if (stat.isDirectory() && recursive) {
2391
- results.push(...findFiles(full, fileGlob, true, depth + 1));
2392
- }
2393
- } catch {
2394
- }
2395
- }
2396
- } catch {
2397
- }
2398
- return results;
2399
- }
2400
- function globToRegex(glob) {
2401
- const escaped = glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
2402
- return new RegExp(`^${escaped}$`);
2403
- }
2404
- async function registerConditions(conditions) {
2405
- try {
2406
- const nodeModule = await import("module");
2407
- const hookCode = [
2408
- `const extra = ${JSON.stringify(conditions)};`,
2409
- `export async function resolve(specifier, context, nextResolve) {`,
2410
- ` return nextResolve(specifier, {`,
2411
- ` ...context,`,
2412
- ` conditions: [...new Set([...context.conditions, ...extra])],`,
2413
- ` });`,
2414
- `}`
2415
- ].join("\n");
2416
- nodeModule.register(`data:text/javascript,${encodeURIComponent(hookCode)}`);
2417
- } catch {
2418
- console.warn("[axl-studio] Warning: import conditions require Node.js 20.6+");
2419
- }
2420
- }
2421
2452
 
2422
2453
  // src/middleware.ts
2423
2454
  var import_meta2 = {};
@@ -2432,9 +2463,9 @@ function createStudioMiddleware(options) {
2432
2463
  const basePath = normalizeBasePath(options.basePath);
2433
2464
  const staticRoot = serveClient ? resolveClientDist() : void 0;
2434
2465
  if (serveClient && !staticRoot) {
2435
- const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url3.fileURLToPath)(import_meta2.url)));
2466
+ const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path3.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url)));
2436
2467
  console.warn(
2437
- `[axl-studio] serveClient is true but no pre-built client found at ${(0, import_node_path4.resolve)(dir, "client")}. Studio UI will not be available. Set serveClient: false to suppress this warning.`
2468
+ `[axl-studio] serveClient is true but no pre-built client found at ${(0, import_node_path3.resolve)(dir, "client")}. Studio UI will not be available. Set serveClient: false to suppress this warning.`
2438
2469
  );
2439
2470
  }
2440
2471
  const evalLoader = options.evals ? createEvalLoader(options.evals, runtime) : void 0;
@@ -2607,9 +2638,9 @@ function normalizeBasePath(raw) {
2607
2638
  return normalized;
2608
2639
  }
2609
2640
  function resolveClientDist() {
2610
- const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url3.fileURLToPath)(import_meta2.url)));
2611
- const candidate = (0, import_node_path4.resolve)(dir, "client");
2612
- return (0, import_node_fs4.existsSync)((0, import_node_path4.resolve)(candidate, "index.html")) ? candidate : void 0;
2641
+ const dir = import_meta2.dirname ?? (typeof __dirname !== "undefined" ? __dirname : (0, import_node_path3.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url)));
2642
+ const candidate = (0, import_node_path3.resolve)(dir, "client");
2643
+ return (0, import_node_fs2.existsSync)((0, import_node_path3.resolve)(candidate, "index.html")) ? candidate : void 0;
2613
2644
  }
2614
2645
  // Annotate the CommonJS export names for ESM import in node:
2615
2646
  0 && (module.exports = {