lmnr-cli 0.1.3 → 0.1.4

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/dist/index.cjs CHANGED
@@ -45,7 +45,7 @@ let readline = require("readline");
45
45
  readline = __toESM(readline);
46
46
 
47
47
  //#region package.json
48
- var version$1 = "0.1.3";
48
+ var version$1 = "0.1.4";
49
49
 
50
50
  //#endregion
51
51
  //#region ../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/package.json
@@ -392,7 +392,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
392
392
  //#endregion
393
393
  //#region ../client/dist/index.mjs
394
394
  var import_main = require_main();
395
- var version = "0.8.6";
395
+ var version = "0.8.7";
396
396
  function getLangVersion() {
397
397
  if (typeof process !== "undefined" && process.versions && process.versions.node) return `node-${process.versions.node}`;
398
398
  if (typeof navigator !== "undefined" && navigator.userAgent) return `browser-${navigator.userAgent}`;
@@ -449,7 +449,7 @@ function initializeLogger$1(options) {
449
449
  minimumLevel: level
450
450
  }));
451
451
  }
452
- const logger$2 = initializeLogger$1();
452
+ const logger$2$1 = initializeLogger$1();
453
453
  const isStringUUID = (id) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id);
454
454
  const newUUID$1 = () => {
455
455
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
@@ -458,9 +458,9 @@ const newUUID$1 = () => {
458
458
  const otelSpanIdToUUID = (spanId) => {
459
459
  let id = spanId.toLowerCase();
460
460
  if (id.startsWith("0x")) id = id.slice(2);
461
- if (id.length !== 16) logger$2.warn(`Span ID ${spanId} is not 16 hex chars long. This is not a valid OpenTelemetry span ID.`);
461
+ if (id.length !== 16) logger$2$1.warn(`Span ID ${spanId} is not 16 hex chars long. This is not a valid OpenTelemetry span ID.`);
462
462
  if (!/^[0-9a-f]+$/.test(id)) {
463
- logger$2.error(`Span ID ${spanId} is not a valid hex string. Generating a random UUID instead.`);
463
+ logger$2$1.error(`Span ID ${spanId} is not a valid hex string. Generating a random UUID instead.`);
464
464
  return newUUID$1();
465
465
  }
466
466
  return id.padStart(32, "0").replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, "$1-$2-$3-$4-$5");
@@ -468,9 +468,9 @@ const otelSpanIdToUUID = (spanId) => {
468
468
  const otelTraceIdToUUID = (traceId) => {
469
469
  let id = traceId.toLowerCase();
470
470
  if (id.startsWith("0x")) id = id.slice(2);
471
- if (id.length !== 32) logger$2.warn(`Trace ID ${traceId} is not 32 hex chars long. This is not a valid OpenTelemetry trace ID.`);
471
+ if (id.length !== 32) logger$2$1.warn(`Trace ID ${traceId} is not 32 hex chars long. This is not a valid OpenTelemetry trace ID.`);
472
472
  if (!/^[0-9a-f]+$/.test(id)) {
473
- logger$2.error(`Trace ID ${traceId} is not a valid hex string. Generating a random UUID instead.`);
473
+ logger$2$1.error(`Trace ID ${traceId} is not a valid hex string. Generating a random UUID instead.`);
474
474
  return newUUID$1();
475
475
  }
476
476
  return id.replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, "$1-$2-$3-$4-$5");
@@ -1314,7 +1314,7 @@ function initializeLogger(options) {
1314
1314
 
1315
1315
  //#endregion
1316
1316
  //#region src/subprocess/executor.ts
1317
- const logger$1 = initializeLogger();
1317
+ const logger$2 = initializeLogger();
1318
1318
  /**
1319
1319
  * Track and kill the currently running subprocess
1320
1320
  */
@@ -1345,19 +1345,19 @@ var SubprocessManager = class {
1345
1345
  const message = JSON.parse(messageJson);
1346
1346
  switch (message.type) {
1347
1347
  case "log":
1348
- logger$1[message.level](message.message);
1348
+ logger$2[message.level](message.message);
1349
1349
  break;
1350
1350
  case "result":
1351
1351
  result = message.data;
1352
1352
  break;
1353
1353
  case "error":
1354
1354
  hasError = true;
1355
- logger$1.error(`Worker error: ${message.error}`);
1356
- if (message.stack) logger$1.error(message.stack);
1355
+ logger$2.error(`Worker error: ${message.error}`);
1356
+ if (message.stack) logger$2.error(message.stack);
1357
1357
  break;
1358
1358
  }
1359
1359
  } catch {
1360
- logger$1.error(`Failed to parse worker protocol message: ${line}`);
1360
+ logger$2.error(`Failed to parse worker protocol message: ${line}`);
1361
1361
  }
1362
1362
  else console.log(line);
1363
1363
  });
@@ -1369,7 +1369,7 @@ var SubprocessManager = class {
1369
1369
  if (signal) reject(/* @__PURE__ */ new Error(`Worker terminated by signal: ${signal}`));
1370
1370
  else if (code === 0) resolve(result);
1371
1371
  else {
1372
- if (!hasError) logger$1.error(`Worker exited with code ${code}`);
1372
+ if (!hasError) logger$2.error(`Worker exited with code ${code}`);
1373
1373
  reject(/* @__PURE__ */ new Error(`Worker exited with code ${code}`));
1374
1374
  }
1375
1375
  });
@@ -1383,6 +1383,7 @@ var SubprocessManager = class {
1383
1383
  }
1384
1384
  /**
1385
1385
  * Kill the currently running subprocess
1386
+ * @returns true if a process was killed, false if no process was running
1386
1387
  */
1387
1388
  kill() {
1388
1389
  if (this.currentProcess) {
@@ -1390,11 +1391,13 @@ var SubprocessManager = class {
1390
1391
  this.currentProcess.kill("SIGTERM");
1391
1392
  setTimeout(() => {
1392
1393
  if (processToKill && processToKill.exitCode === null) {
1393
- logger$1.warn("Child process did not terminate, using SIGKILL");
1394
+ logger$2.warn("Child process did not terminate, using SIGKILL");
1394
1395
  processToKill.kill("SIGKILL");
1395
1396
  }
1396
1397
  }, 5e3);
1398
+ return true;
1397
1399
  }
1400
+ return false;
1398
1401
  }
1399
1402
  /**
1400
1403
  * Check if a subprocess is currently running
@@ -1482,8 +1485,8 @@ function getWorkerCommand(filePath, options) {
1482
1485
  }
1483
1486
 
1484
1487
  //#endregion
1485
- //#region src/commands/dev.ts
1486
- const logger = initializeLogger();
1488
+ //#region src/commands/dev/metadata.ts
1489
+ const logger$1 = initializeLogger();
1487
1490
  const TS_JS_EXTENSIONS = [
1488
1491
  ".ts",
1489
1492
  ".tsx",
@@ -1495,8 +1498,13 @@ const TS_JS_EXTENSIONS = [
1495
1498
  ".cts"
1496
1499
  ];
1497
1500
  const EXTENSIONS_TO_DISCOVER_METADATA = [...TS_JS_EXTENSIONS, ".py"];
1501
+ /**
1502
+ * Protocol prefix for metadata discovery responses
1503
+ * This allows us to safely parse JSON even if there are other log statements in stdout
1504
+ */
1505
+ const METADATA_PROTOCOL_PREFIX = "LMNR_METADATA:";
1498
1506
  const logLmnrPackageNotFoundAndExit = () => {
1499
- logger.error("@lmnr-ai/lmnr package not found or outdated. For JS/TS projects, please install the latest version of @lmnr-ai/lmnr in your project: npm install @lmnr-ai/lmnr\nYou might need to run `lmnr-cli` from the root of your project");
1507
+ logger$1.error("@lmnr-ai/lmnr package not found or outdated. For JS/TS projects, please install the latest version of @lmnr-ai/lmnr in your project: npm install @lmnr-ai/lmnr\nYou might need to run `lmnr-cli` from the root of your project");
1500
1508
  process.exit(1);
1501
1509
  };
1502
1510
  /**
@@ -1526,20 +1534,20 @@ const discoverTypeScriptMetadata = async (filePath, options) => {
1526
1534
  loadModule = buildModule.loadModule;
1527
1535
  selectRolloutFunction = buildModule.selectRolloutFunction;
1528
1536
  if (!extractRolloutFunctions || !buildFile || !loadModule || !selectRolloutFunction) {
1529
- logger.error("Missing exports from @lmnr-ai/lmnr modules. This may indicate an outdated package version.");
1537
+ logger$1.error("Missing exports from @lmnr-ai/lmnr modules. This may indicate an outdated package version.");
1530
1538
  logLmnrPackageNotFoundAndExit();
1531
1539
  }
1532
1540
  } catch (error) {
1533
1541
  if (error.code === "MODULE_NOT_FOUND") logLmnrPackageNotFoundAndExit();
1534
- logger.error(`Unexpected error loading @lmnr-ai/lmnr modules: ${error.message}`);
1542
+ logger$1.error(`Unexpected error loading @lmnr-ai/lmnr modules: ${error.message}`);
1535
1543
  throw error;
1536
1544
  }
1537
1545
  let paramsMetadata;
1538
1546
  try {
1539
1547
  paramsMetadata = extractRolloutFunctions(filePath);
1540
- logger.debug(`Extracted TypeScript metadata for ${paramsMetadata?.size} functions`);
1548
+ logger$1.debug(`Extracted TypeScript metadata for ${paramsMetadata?.size} functions`);
1541
1549
  } catch (error) {
1542
- logger.warn("Failed to extract TypeScript metadata, falling back to runtime parsing: " + (error instanceof Error ? error.message : String(error)));
1550
+ logger$1.warn("Failed to extract TypeScript metadata, falling back to runtime parsing: " + (error instanceof Error ? error.message : String(error)));
1543
1551
  }
1544
1552
  const moduleText = await buildFile(filePath, {
1545
1553
  externalPackages: options.externalPackages,
@@ -1551,21 +1559,21 @@ const discoverTypeScriptMetadata = async (filePath, options) => {
1551
1559
  });
1552
1560
  const selectedFunction = selectRolloutFunction(options.function);
1553
1561
  if (paramsMetadata) {
1554
- logger.debug(`Available TS metadata keys: ${Array.from(paramsMetadata.keys()).join(", ")}`);
1555
- logger.debug(`Looking for span name: ${selectedFunction.name} (runtime key: ${selectedFunction.exportName})`);
1562
+ logger$1.debug(`Available TS metadata keys: ${Array.from(paramsMetadata.keys()).join(", ")}`);
1563
+ logger$1.debug(`Looking for span name: ${selectedFunction.name} (runtime key: ${selectedFunction.exportName})`);
1556
1564
  let foundMetadata = null;
1557
1565
  for (const [exportName, metadata] of paramsMetadata.entries()) {
1558
- logger.debug(`Checking ${exportName}: span name = ${metadata.name}, export name = ${exportName}`);
1566
+ logger$1.debug(`Checking ${exportName}: span name = ${metadata.name}, export name = ${exportName}`);
1559
1567
  if (metadata.name === selectedFunction.name) {
1560
1568
  foundMetadata = metadata;
1561
- logger.debug(`Match. Export name: ${exportName}, span name: ${metadata.name}`);
1569
+ logger$1.debug(`Match. Export name: ${exportName}, span name: ${metadata.name}`);
1562
1570
  break;
1563
1571
  }
1564
1572
  }
1565
1573
  if (foundMetadata) {
1566
1574
  selectedFunction.params = foundMetadata.params;
1567
- logger.debug(`Using TypeScript metadata for span: ${selectedFunction.name}`);
1568
- } else logger.info(`No TypeScript metadata found for span name: ${selectedFunction.name}`);
1575
+ logger$1.debug(`Using TypeScript metadata for span: ${selectedFunction.name}`);
1576
+ } else logger$1.info(`No TypeScript metadata found for span name: ${selectedFunction.name}`);
1569
1577
  }
1570
1578
  return {
1571
1579
  functionName: selectedFunction.name,
@@ -1598,11 +1606,6 @@ const execCommand = async (command, args) => new Promise((resolve, reject) => {
1598
1606
  });
1599
1607
  });
1600
1608
  /**
1601
- * Protocol prefix for metadata discovery responses
1602
- * This allows us to safely parse JSON even if there are other log statements in stdout
1603
- */
1604
- const METADATA_PROTOCOL_PREFIX = "LMNR_METADATA:";
1605
- /**
1606
1609
  * Extracts JSON metadata from stdout that may contain other log statements
1607
1610
  * Looks for lines matching the protocol prefix and parses the JSON payload
1608
1611
  *
@@ -1680,7 +1683,7 @@ const extractMetadataFromStdout = (stdout) => {
1680
1683
  * Discovers function metadata for Python files/modules by calling the lmnr Python CLI
1681
1684
  */
1682
1685
  const discoverPythonMetadata = async (filePathOrModule, options) => {
1683
- logger.debug(`Discovering Python metadata for ${filePathOrModule}`);
1686
+ logger$1.debug(`Discovering Python metadata for ${filePathOrModule}`);
1684
1687
  const args = ["discover"];
1685
1688
  if (options.pythonModule) args.push("--module", options.pythonModule);
1686
1689
  else args.push("--file", filePathOrModule);
@@ -1693,9 +1696,9 @@ const discoverPythonMetadata = async (filePathOrModule, options) => {
1693
1696
  };
1694
1697
  } catch (error) {
1695
1698
  const errorMessage = error instanceof Error ? error.message : String(error);
1696
- logger.error(`Failed to discover Python metadata: ${errorMessage}`);
1699
+ logger$1.error(`Failed to discover Python metadata: ${errorMessage}`);
1697
1700
  if (errorMessage.toLowerCase().includes("command not found") || errorMessage.includes("spawn lmnr ENOENT")) {
1698
- logger.info(`HINT: Make sure latest version of \`lmnr\` python package is installed. \`pip install --upgrade lmnr\`, or if you are running this command from a virtual environment, make sure to activate it. For \`uv\` users, rerun the command with \`uv run\`, e.g. "uv run npx lmnr-cli dev ${filePathOrModule}"`);
1701
+ logger$1.info(`HINT: Make sure latest version of \`lmnr\` python package is installed. \`pip install --upgrade lmnr\`, or if you are running this command from a virtual environment, make sure to activate it. For \`uv\` users, rerun the command with \`uv run\`, e.g. "uv run npx lmnr-cli dev ${filePathOrModule}"`);
1699
1702
  process.exit(1);
1700
1703
  }
1701
1704
  const defaultName = options.pythonModule ? options.pythonModule.split(".").pop() || "main" : path.basename(filePathOrModule, ".py");
@@ -1713,12 +1716,16 @@ const discoverFunctionMetadata = async (filePathOrModule, options) => {
1713
1716
  const ext = path.extname(filePathOrModule);
1714
1717
  if (TS_JS_EXTENSIONS.includes(ext)) return await discoverTypeScriptMetadata(filePathOrModule, options);
1715
1718
  if (ext === ".py") return await discoverPythonMetadata(filePathOrModule, options);
1716
- logger.warn(`No metadata discovery available for ${ext} files`);
1719
+ logger$1.warn(`No metadata discovery available for ${ext} files`);
1717
1720
  return {
1718
1721
  functionName: options.function || path.basename(filePathOrModule, ext),
1719
1722
  params: []
1720
1723
  };
1721
1724
  };
1725
+
1726
+ //#endregion
1727
+ //#region src/commands/dev/index.ts
1728
+ const logger = initializeLogger();
1722
1729
  function newUUID() {
1723
1730
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
1724
1731
  return (0, uuid.v4)();
@@ -1958,17 +1965,52 @@ async function runDev(filePath, options = {}) {
1958
1965
  params,
1959
1966
  name: functionName ?? ""
1960
1967
  });
1968
+ let currentRunPromise = null;
1969
+ let stopRequested = false;
1961
1970
  sseClient.on("heartbeat", () => {
1962
1971
  logger.debug("Heartbeat received");
1963
1972
  });
1964
1973
  sseClient.on("run", (event) => {
1965
- if (subprocessManager.isRunning()) {
1966
- logger.warn("Rollout is already running, skipping new run");
1974
+ if (currentRunPromise !== null) {
1975
+ logger.warn("Already processing a run event, skipping new run");
1967
1976
  return;
1968
1977
  }
1969
- handleRunEvent(event, sessionId, filePathOrModule, client, cacheServerPort, cache, setMetadata, options, subprocessManager).catch((error) => {
1970
- logger.error("Unhandled error in run event handler: " + (error instanceof Error ? error.message : String(error)));
1971
- });
1978
+ currentRunPromise = (async () => {
1979
+ try {
1980
+ stopRequested = false;
1981
+ if (reloadScheduled) {
1982
+ logger.info("Reloading function metadata before run...");
1983
+ if (isPythonModule || filePath && EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath))) try {
1984
+ const metadata = await discoverFunctionMetadata(filePathOrModule, options);
1985
+ if (stopRequested) {
1986
+ logger.info("Run cancelled during metadata discovery");
1987
+ return;
1988
+ }
1989
+ logger.debug(`Updated function metadata: ${metadata.functionName}`);
1990
+ logger.debug(`Updated parameters: ${JSON.stringify(metadata.params, null, 2)}`);
1991
+ if (sseClient) {
1992
+ sseClient.updateMetadata(metadata.params, metadata.functionName);
1993
+ logger.debug("Notified backend of metadata changes");
1994
+ }
1995
+ reloadScheduled = false;
1996
+ } catch (error) {
1997
+ logger.error("Failed to update function metadata: " + (error instanceof Error ? error.message : String(error)));
1998
+ if (error instanceof Error && error.stack) logger.debug(`Stack trace: ${error.stack}`);
1999
+ return;
2000
+ }
2001
+ else reloadScheduled = false;
2002
+ }
2003
+ if (stopRequested) {
2004
+ logger.info("Run cancelled before execution");
2005
+ return;
2006
+ }
2007
+ await handleRunEvent(event, sessionId, filePathOrModule, client, cacheServerPort, cache, setMetadata, options, subprocessManager);
2008
+ } catch (error) {
2009
+ logger.error("Unhandled error in run event handler: " + (error instanceof Error ? error.message : String(error)));
2010
+ } finally {
2011
+ currentRunPromise = null;
2012
+ }
2013
+ })();
1972
2014
  });
1973
2015
  sseClient.on("handshake", (event) => {
1974
2016
  const projectId = event.data.project_id;
@@ -1987,32 +2029,19 @@ async function runDev(filePath, options = {}) {
1987
2029
  logger.debug("Heartbeat timeout, reconnecting...");
1988
2030
  });
1989
2031
  sseClient.on("stop", () => {
1990
- logger.debug("Cancelling current run...");
1991
- subprocessManager.kill();
1992
- logger.info("Current run cancelled");
2032
+ logger.debug("Stop event received");
2033
+ stopRequested = true;
2034
+ if (subprocessManager.kill()) logger.info("Current run cancelled");
1993
2035
  });
1994
2036
  let reloadTimeout = null;
2037
+ let reloadScheduled = false;
1995
2038
  watcher.on("change", (changedPath) => {
1996
- logger.info(`File changed: ${changedPath}, reloading...`);
2039
+ logger.info(`File changed: ${changedPath}, scheduling reload...`);
1997
2040
  if (reloadTimeout) clearTimeout(reloadTimeout);
1998
- if (subprocessManager.isRunning()) {
1999
- logger.warn("Cancelling current run due to file change");
2000
- subprocessManager.kill();
2001
- }
2002
2041
  reloadTimeout = setTimeout(() => {
2003
- logger.debug("Executing debounced reload...");
2042
+ logger.debug("Marking reload as scheduled for next run...");
2004
2043
  reloadTimeout = null;
2005
- if (isPythonModule || filePath && EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath))) discoverFunctionMetadata(filePathOrModule, options).then((metadata) => {
2006
- logger.debug(`Updated function metadata: ${metadata.functionName}`);
2007
- logger.debug(`Updated parameters: ${JSON.stringify(metadata.params, null, 2)}`);
2008
- if (sseClient) {
2009
- sseClient.updateMetadata(metadata.params, metadata.functionName);
2010
- logger.debug("Notified backend of metadata changes");
2011
- }
2012
- }).catch((error) => {
2013
- logger.error("Failed to update function metadata: " + (error instanceof Error ? error.message : String(error)));
2014
- if (error instanceof Error && error.stack) logger.debug(`Stack trace: ${error.stack}`);
2015
- });
2044
+ reloadScheduled = true;
2016
2045
  }, 100);
2017
2046
  });
2018
2047
  const shutdown = () => {
@@ -2021,6 +2050,7 @@ async function runDev(filePath, options = {}) {
2021
2050
  clearTimeout(reloadTimeout);
2022
2051
  reloadTimeout = null;
2023
2052
  }
2053
+ reloadScheduled = false;
2024
2054
  logger.debug("Closing file watcher...");
2025
2055
  watcher.close().catch((error) => {
2026
2056
  logger.error(`Failed to close file watcher: ${error instanceof Error ? error.message : error}`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["path","crypto","initializeLogger","newUUID","logger$1","logger","metadata: CacheMetadata","path","response: CacheServerResponse","EventEmitter","error: any","runEvent: RolloutRunEvent","handshakeEvent: RolloutHandshakeEvent","logger","child: ChildProcess","result: any","message: WorkerMessage","config","DEFAULT_WORKERS: Record<string, WorkerCommand>","extractRolloutFunctions: any","buildFile: any","loadModule: any","selectRolloutFunction: any","error: any","paramsMetadata: Map<string, FunctionMetadata> | undefined","foundMetadata: FunctionMetadata | null","spawn","prefixPositions: number[]","lastValidJson: any","spansByPath: Record<string, any[]>","path","cachedSpan: CachedSpan","env: Record<string, string>","workerConfig: WorkerConfig","error","params: RolloutParam[]","sseClient: SSEClient | null","sessionId","reloadTimeout: NodeJS.Timeout | null","Command","version"],"sources":["../package.json","../../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/package.json","../../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/lib/main.js","../../client/dist/index.mjs","../src/cache-server.ts","../src/sse-client.ts","../../types/dist/index.mjs","../src/utils.ts","../src/subprocess/executor.ts","../src/worker-registry.ts","../src/commands/dev.ts","../src/index.ts"],"sourcesContent":["","","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\n// Array of tips to display randomly\nconst TIPS = [\n '🔐 encrypt with Dotenvx: https://dotenvx.com',\n '🔐 prevent committing .env to code: https://dotenvx.com/precommit',\n '🔐 prevent building .env in docker: https://dotenvx.com/prebuild',\n '📡 add observability to secrets: https://dotenvx.com/ops',\n '👥 sync secrets across teammates & machines: https://dotenvx.com/ops',\n '🗂️ backup and recover secrets: https://dotenvx.com/ops',\n '✅ audit secrets and track compliance: https://dotenvx.com/ops',\n '🔄 add secrets lifecycle management: https://dotenvx.com/ops',\n '🔑 add access controls to secrets: https://dotenvx.com/ops',\n '🛠️ run anywhere with `dotenvx run -- yourcommand`',\n '⚙️ specify custom .env file path with { path: \\'/custom/path/.env\\' }',\n '⚙️ enable debug logging with { debug: true }',\n '⚙️ override existing env vars with { override: true }',\n '⚙️ suppress all logs with { quiet: true }',\n '⚙️ write to custom object with { processEnv: myObject }',\n '⚙️ load multiple .env files with { path: [\\'.env.local\\', \\'.env\\'] }'\n]\n\n// Get a random tip from the tips array\nfunction _getRandomTip () {\n return TIPS[Math.floor(Math.random() * TIPS.length)]\n}\n\nfunction parseBoolean (value) {\n if (typeof value === 'string') {\n return !['false', '0', 'no', 'off', ''].includes(value.toLowerCase())\n }\n return Boolean(value)\n}\n\nfunction supportsAnsi () {\n return process.stdout.isTTY // && process.env.TERM !== 'dumb'\n}\n\nfunction dim (text) {\n return supportsAnsi() ? `\\x1b[2m${text}\\x1b[0m` : text\n}\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n const obj = {}\n\n // Convert buffer to string\n let lines = src.toString()\n\n // Convert line breaks to same format\n lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n let match\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] || '')\n\n // Remove whitespace\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n obj[key] = value\n }\n\n return obj\n}\n\nfunction _parseVault (options) {\n options = options || {}\n\n const vaultPath = _vaultPath(options)\n options.path = vaultPath // parse .env.vault\n const result = DotenvModule.configDotenv(options)\n if (!result.parsed) {\n const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n err.code = 'MISSING_DATA'\n throw err\n }\n\n // handle scenario for comma separated keys - for use with key rotation\n // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n const keys = _dotenvKey(options).split(',')\n const length = keys.length\n\n let decrypted\n for (let i = 0; i < length; i++) {\n try {\n // Get full key\n const key = keys[i].trim()\n\n // Get instructions for decrypt\n const attrs = _instructions(result, key)\n\n // Decrypt\n decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n break\n } catch (error) {\n // last key\n if (i + 1 >= length) {\n throw error\n }\n // try next key\n }\n }\n\n // Parse decrypted .env string\n return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n console.error(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _log (message) {\n console.log(`[dotenv@${version}] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n // prioritize developer directly setting options.DOTENV_KEY\n if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n return options.DOTENV_KEY\n }\n\n // secondary infra already contains a DOTENV_KEY environment variable\n if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n return process.env.DOTENV_KEY\n }\n\n // fallback to empty string\n return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n // Parse DOTENV_KEY. Format is a URI\n let uri\n try {\n uri = new URL(dotenvKey)\n } catch (error) {\n if (error.code === 'ERR_INVALID_URL') {\n const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n throw error\n }\n\n // Get decrypt key\n const key = uri.password\n if (!key) {\n const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get environment\n const environment = uri.searchParams.get('environment')\n if (!environment) {\n const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get ciphertext payload\n const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n if (!ciphertext) {\n const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n throw err\n }\n\n return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n let possibleVaultPath = null\n\n if (options && options.path && options.path.length > 0) {\n if (Array.isArray(options.path)) {\n for (const filepath of options.path) {\n if (fs.existsSync(filepath)) {\n possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n }\n }\n } else {\n possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n }\n } else {\n possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n }\n\n if (fs.existsSync(possibleVaultPath)) {\n return possibleVaultPath\n }\n\n return null\n}\n\nfunction _resolveHome (envPath) {\n return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || (options && options.debug))\n const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (debug || !quiet) {\n _log('Loading env from encrypted .env.vault')\n }\n\n const parsed = DotenvModule._parseVault(options)\n\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n\n DotenvModule.populate(processEnv, parsed, options)\n\n return { parsed }\n}\n\nfunction configDotenv (options) {\n const dotenvPath = path.resolve(process.cwd(), '.env')\n let encoding = 'utf8'\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || (options && options.debug))\n let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (options && options.encoding) {\n encoding = options.encoding\n } else {\n if (debug) {\n _debug('No encoding is specified. UTF-8 is used by default')\n }\n }\n\n let optionPaths = [dotenvPath] // default, look for .env\n if (options && options.path) {\n if (!Array.isArray(options.path)) {\n optionPaths = [_resolveHome(options.path)]\n } else {\n optionPaths = [] // reset default\n for (const filepath of options.path) {\n optionPaths.push(_resolveHome(filepath))\n }\n }\n }\n\n // Build the parsed data in a temporary object (because we need to return it). Once we have the final\n // parsed data, we will combine it with process.env (or options.processEnv if provided).\n let lastError\n const parsedAll = {}\n for (const path of optionPaths) {\n try {\n // Specifying an encoding returns a string instead of a buffer\n const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n DotenvModule.populate(parsedAll, parsed, options)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${path} ${e.message}`)\n }\n lastError = e\n }\n }\n\n const populated = DotenvModule.populate(processEnv, parsedAll, options)\n\n // handle user settings DOTENV_CONFIG_ options inside .env file(s)\n debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug)\n quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet)\n\n if (debug || !quiet) {\n const keysCount = Object.keys(populated).length\n const shortPaths = []\n for (const filePath of optionPaths) {\n try {\n const relative = path.relative(process.cwd(), filePath)\n shortPaths.push(relative)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${filePath} ${e.message}`)\n }\n lastError = e\n }\n }\n\n _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`-- tip: ${_getRandomTip()}`)}`)\n }\n\n if (lastError) {\n return { parsed: parsedAll, error: lastError }\n } else {\n return { parsed: parsedAll }\n }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n // fallback to original dotenv if DOTENV_KEY is not set\n if (_dotenvKey(options).length === 0) {\n return DotenvModule.configDotenv(options)\n }\n\n const vaultPath = _vaultPath(options)\n\n // dotenvKey exists but .env.vault file does not exist\n if (!vaultPath) {\n _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n return DotenvModule.configDotenv(options)\n }\n\n return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n const key = Buffer.from(keyStr.slice(-64), 'hex')\n let ciphertext = Buffer.from(encrypted, 'base64')\n\n const nonce = ciphertext.subarray(0, 12)\n const authTag = ciphertext.subarray(-16)\n ciphertext = ciphertext.subarray(12, -16)\n\n try {\n const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n aesgcm.setAuthTag(authTag)\n return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n } catch (error) {\n const isRange = error instanceof RangeError\n const invalidKeyLength = error.message === 'Invalid key length'\n const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n if (isRange || invalidKeyLength) {\n const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n } else if (decryptionFailed) {\n const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n err.code = 'DECRYPTION_FAILED'\n throw err\n } else {\n throw error\n }\n }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n const debug = Boolean(options && options.debug)\n const override = Boolean(options && options.override)\n const populated = {}\n\n if (typeof parsed !== 'object') {\n const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n err.code = 'OBJECT_REQUIRED'\n throw err\n }\n\n // Set process.env\n for (const key of Object.keys(parsed)) {\n if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n if (override === true) {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n\n if (debug) {\n if (override === true) {\n _debug(`\"${key}\" is already defined and WAS overwritten`)\n } else {\n _debug(`\"${key}\" is already defined and was NOT overwritten`)\n }\n }\n } else {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n }\n\n return populated\n}\n\nconst DotenvModule = {\n configDotenv,\n _configVault,\n _parseVault,\n config,\n decrypt,\n parse,\n populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","import { config } from \"dotenv\";\nimport * as path from \"path\";\nimport pino from \"pino\";\nimport { PinoPretty } from \"pino-pretty\";\nimport { v4 } from \"uuid\";\n\n//#region package.json\nvar version = \"0.8.6\";\n\n//#endregion\n//#region src/version.ts\nfunction getLangVersion() {\n\tif (typeof process !== \"undefined\" && process.versions && process.versions.node) return `node-${process.versions.node}`;\n\tif (typeof navigator !== \"undefined\" && navigator.userAgent) return `browser-${navigator.userAgent}`;\n\treturn null;\n}\n\n//#endregion\n//#region src/resources/index.ts\nvar BaseResource = class {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tthis.baseHttpUrl = baseHttpUrl;\n\t\tthis.projectApiKey = projectApiKey;\n\t}\n\theaders() {\n\t\treturn {\n\t\t\tAuthorization: `Bearer ${this.projectApiKey}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\"\n\t\t};\n\t}\n\tasync handleError(response) {\n\t\tconst errorMsg = await response.text();\n\t\tthrow new Error(`${response.status} ${errorMsg}`);\n\t}\n};\n\n//#endregion\n//#region src/resources/browser-events.ts\nvar BrowserEventsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync send({ sessionId, traceId, events }) {\n\t\tconst payload = {\n\t\t\tsessionId,\n\t\t\ttraceId,\n\t\t\tevents,\n\t\t\tsource: getLangVersion() ?? \"javascript\",\n\t\t\tsdkVersion: version\n\t\t};\n\t\tconst jsonString = JSON.stringify(payload);\n\t\tconst compressedStream = new Blob([jsonString], { type: \"application/json\" }).stream().pipeThrough(new CompressionStream(\"gzip\"));\n\t\tconst compressedData = await new Response(compressedStream).arrayBuffer();\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/browser-sessions/events\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...this.headers(),\n\t\t\t\t\"Content-Encoding\": \"gzip\"\n\t\t\t},\n\t\t\tbody: compressedData\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/utils.ts\nfunction initializeLogger(options) {\n\tconst colorize = options?.colorize ?? true;\n\tconst level = options?.level ?? process.env.LMNR_LOG_LEVEL?.toLowerCase()?.trim() ?? \"info\";\n\treturn pino({ level }, PinoPretty({\n\t\tcolorize,\n\t\tminimumLevel: level\n\t}));\n}\nconst logger$2 = initializeLogger();\nconst isStringUUID = (id) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id);\nconst newUUID = () => {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n\telse return v4();\n};\nconst otelSpanIdToUUID = (spanId) => {\n\tlet id = spanId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 16) logger$2.warn(`Span ID ${spanId} is not 16 hex chars long. This is not a valid OpenTelemetry span ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$2.error(`Span ID ${spanId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.padStart(32, \"0\").replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst otelTraceIdToUUID = (traceId) => {\n\tlet id = traceId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 32) logger$2.warn(`Trace ID ${traceId} is not 32 hex chars long. This is not a valid OpenTelemetry trace ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$2.error(`Trace ID ${traceId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst slicePayload = (value, length) => {\n\tif (value === null || value === void 0) return value;\n\tconst str = JSON.stringify(value);\n\tif (str.length <= length) return value;\n\treturn str.slice(0, length) + \"...\";\n};\nconst loadEnv = (options) => {\n\tconst nodeEnv = process.env.NODE_ENV || \"development\";\n\tconst envDir = process.cwd();\n\tconst envFiles = [\n\t\t\".env\",\n\t\t\".env.local\",\n\t\t`.env.${nodeEnv}`,\n\t\t`.env.${nodeEnv}.local`\n\t];\n\tconst logLevel = process.env.LMNR_LOG_LEVEL ?? \"info\";\n\tconst verbose = [\"debug\", \"trace\"].includes(logLevel.trim().toLowerCase());\n\tconst quiet = options?.quiet ?? !verbose;\n\tconfig({\n\t\tpath: options?.paths ?? envFiles.map((envFile) => path.resolve(envDir, envFile)),\n\t\tquiet\n\t});\n};\n\n//#endregion\n//#region src/resources/datasets.ts\nconst logger$1 = initializeLogger();\nconst DEFAULT_DATASET_PULL_LIMIT = 100;\nconst DEFAULT_DATASET_PUSH_BATCH_SIZE = 100;\nvar DatasetsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* List all datasets.\n\t*\n\t* @returns {Promise<Dataset[]>} Array of datasets\n\t*/\n\tasync listDatasets() {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/datasets\", {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Get a dataset by name.\n\t*\n\t* @param {string} name - Name of the dataset\n\t* @returns {Promise<Dataset[]>} Array of datasets with matching name\n\t*/\n\tasync getDatasetByName(name) {\n\t\tconst params = new URLSearchParams({ name });\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Push datapoints to a dataset.\n\t*\n\t* @param {Object} options - Push options\n\t* @param {Datapoint<D, T>[]} options.points - Datapoints to push\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.batchSize] - Batch size for pushing (default: 100)\n\t* @param {boolean} [options.createDataset] - Whether to create the dataset if it doesn't exist\n\t* @returns {Promise<PushDatapointsResponse | undefined>}\n\t*/\n\tasync push({ points, name, id, batchSize = DEFAULT_DATASET_PUSH_BATCH_SIZE, createDataset = false }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tif (createDataset && !name) throw new Error(\"Name must be provided when creating a new dataset\");\n\t\tconst identifier = name ? { name } : { datasetId: id };\n\t\tconst totalBatches = Math.ceil(points.length / batchSize);\n\t\tlet response;\n\t\tfor (let i = 0; i < points.length; i += batchSize) {\n\t\t\tconst batchNum = Math.floor(i / batchSize) + 1;\n\t\t\tlogger$1.debug(`Pushing batch ${batchNum} of ${totalBatches}`);\n\t\t\tconst batch = points.slice(i, i + batchSize);\n\t\t\tconst fetchResponse = await fetch(this.baseHttpUrl + \"/v1/datasets/datapoints\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t...identifier,\n\t\t\t\t\tdatapoints: batch.map((point) => ({\n\t\t\t\t\t\tdata: point.data,\n\t\t\t\t\t\ttarget: point.target ?? {},\n\t\t\t\t\t\tmetadata: point.metadata ?? {}\n\t\t\t\t\t})),\n\t\t\t\t\tcreateDataset\n\t\t\t\t})\n\t\t\t});\n\t\t\tif (fetchResponse.status !== 200 && fetchResponse.status !== 201) await this.handleError(fetchResponse);\n\t\t\tresponse = await fetchResponse.json();\n\t\t}\n\t\treturn response;\n\t}\n\t/**\n\t* Pull datapoints from a dataset.\n\t*\n\t* @param {Object} options - Pull options\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.limit] - Maximum number of datapoints to return (default: 100)\n\t* @param {number} [options.offset] - Offset for pagination (default: 0)\n\t* @returns {Promise<GetDatapointsResponse<D, T>>}\n\t*/\n\tasync pull({ name, id, limit = DEFAULT_DATASET_PULL_LIMIT, offset = 0 }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tconst paramsObj = {\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t};\n\t\tif (name) paramsObj.name = name;\n\t\telse paramsObj.datasetId = id;\n\t\tconst params = new URLSearchParams(paramsObj);\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n\n//#endregion\n//#region src/resources/evals.ts\nconst logger = initializeLogger();\nconst INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH = 16e6;\nvar EvalsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Initialize an evaluation.\n\t*\n\t* @param {string} name - Name of the evaluation\n\t* @param {string} groupName - Group name of the evaluation\n\t* @param {Record<string, any>} metadata - Optional metadata\n\t* @returns {Promise<InitEvaluationResponse>} Response from the evaluation initialization\n\t*/\n\tasync init(name, groupName, metadata) {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evals\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname: name ?? null,\n\t\t\t\tgroupName: groupName ?? null,\n\t\t\t\tmetadata: metadata ?? null\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t*\n\t* @param {string} [name] - Optional name of the evaluation\n\t* @param {string} [groupName] - An identifier to group evaluations\n\t* @param {Record<string, any>} [metadata] - Optional metadata\n\t* @returns {Promise<StringUUID>} The evaluation ID\n\t*/\n\tasync create(args) {\n\t\treturn (await this.init(args?.name, args?.groupName, args?.metadata)).id;\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t* @deprecated use `create` instead.\n\t*/\n\tasync createEvaluation(name, groupName, metadata) {\n\t\treturn (await this.init(name, groupName, metadata)).id;\n\t}\n\t/**\n\t* Create a datapoint for an evaluation.\n\t*\n\t* @param {Object} options - Create datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {D} options.data - The input data for the executor\n\t* @param {T} [options.target] - The target/expected output for evaluators\n\t* @param {Record<string, any>} [options.metadata] - Optional metadata\n\t* @param {number} [options.index] - Optional index of the datapoint\n\t* @param {string} [options.traceId] - Optional trace ID\n\t* @returns {Promise<StringUUID>} The datapoint ID\n\t*/\n\tasync createDatapoint({ evalId, data, target, metadata, index, traceId }) {\n\t\tconst datapointId = newUUID();\n\t\tconst partialDatapoint = {\n\t\t\tid: datapointId,\n\t\t\tdata,\n\t\t\ttarget,\n\t\t\tindex: index ?? 0,\n\t\t\ttraceId: traceId ?? newUUID(),\n\t\t\texecutorSpanId: newUUID(),\n\t\t\tmetadata\n\t\t};\n\t\tawait this.saveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints: [partialDatapoint]\n\t\t});\n\t\treturn datapointId;\n\t}\n\t/**\n\t* Update a datapoint with evaluation results.\n\t*\n\t* @param {Object} options - Update datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {string} options.datapointId - The datapoint ID\n\t* @param {Record<string, number>} options.scores - The scores\n\t* @param {O} [options.executorOutput] - The executor output\n\t* @returns {Promise<void>}\n\t*/\n\tasync updateDatapoint({ evalId, datapointId, scores, executorOutput }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints/${datapointId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\texecutorOutput,\n\t\t\t\tscores\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Save evaluation datapoints.\n\t*\n\t* @param {Object} options - Save datapoints options\n\t* @param {string} options.evalId - ID of the evaluation\n\t* @param {EvaluationDatapoint<D, T, O>[]} options.datapoints - Datapoint to add\n\t* @param {string} [options.groupName] - Group name of the evaluation\n\t* @returns {Promise<void>} Response from the datapoint addition\n\t*/\n\tasync saveDatapoints({ evalId, datapoints, groupName }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t...d,\n\t\t\t\t\tdata: slicePayload(d.data, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\ttarget: slicePayload(d.target, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH)\n\t\t\t\t})),\n\t\t\t\tgroupName: groupName ?? null\n\t\t\t})\n\t\t});\n\t\tif (response.status === 413) return await this.retrySaveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints,\n\t\t\tgroupName\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Get evaluation datapoints.\n\t*\n\t* @deprecated Use `client.datasets.pull()` instead.\n\t* @param {Object} options - Get datapoints options\n\t* @param {string} options.datasetName - Name of the dataset\n\t* @param {number} options.offset - Offset at which to start the query\n\t* @param {number} options.limit - Maximum number of datapoints to return\n\t* @returns {Promise<GetDatapointsResponse>} Response from the datapoint retrieval\n\t*/\n\tasync getDatapoints({ datasetName, offset, limit }) {\n\t\tlogger.warn(\"evals.getDatapoints() is deprecated. Use client.datasets.pull() instead.\");\n\t\tconst params = new URLSearchParams({\n\t\t\tname: datasetName,\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t});\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn await response.json();\n\t}\n\tasync retrySaveDatapoints({ evalId, datapoints, groupName, maxRetries = 25, initialLength = INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH }) {\n\t\tlet length = initialLength;\n\t\tlet lastResponse = null;\n\t\tfor (let i = 0; i < maxRetries; i++) {\n\t\t\tlogger.debug(`Retrying save datapoints... ${i + 1} of ${maxRetries}, length: ${length}`);\n\t\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t\t...d,\n\t\t\t\t\t\tdata: slicePayload(d.data, length),\n\t\t\t\t\t\ttarget: slicePayload(d.target, length),\n\t\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, length)\n\t\t\t\t\t})),\n\t\t\t\t\tgroupName: groupName ?? null\n\t\t\t\t})\n\t\t\t});\n\t\t\tlastResponse = response;\n\t\t\tlength = Math.floor(length / 2);\n\t\t\tif (response.status !== 413) break;\n\t\t}\n\t\tif (lastResponse && !lastResponse.ok) await this.handleError(lastResponse);\n\t}\n};\n\n//#endregion\n//#region src/resources/evaluators.ts\nvar EvaluatorScoreSourceType = /* @__PURE__ */ function(EvaluatorScoreSourceType$1) {\n\tEvaluatorScoreSourceType$1[\"Evaluator\"] = \"Evaluator\";\n\tEvaluatorScoreSourceType$1[\"Code\"] = \"Code\";\n\treturn EvaluatorScoreSourceType$1;\n}(EvaluatorScoreSourceType || {});\n/**\n* Resource for creating evaluator scores\n*/\nvar EvaluatorsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Create a score for a span or trace\n\t*\n\t* @param {ScoreOptions} options - Score creation options\n\t* @param {string} options.name - Name of the score\n\t* @param {string} [options.traceId] - The trace ID to score (will be attached to top-level span)\n\t* @param {string} [options.spanId] - The span ID to score\n\t* @param {Record<string, any>} [options.metadata] - Additional metadata\n\t* @param {number} options.score - The score value (float)\n\t* @returns {Promise<void>}\n\t*\n\t* @example\n\t* // Score by trace ID (will attach to root span)\n\t* await evaluators.score({\n\t* name: \"quality\",\n\t* traceId: \"trace-id-here\",\n\t* score: 0.95,\n\t* metadata: { model: \"gpt-4\" }\n\t* });\n\t*\n\t* @example\n\t* // Score by span ID\n\t* await evaluators.score({\n\t* name: \"relevance\",\n\t* spanId: \"span-id-here\",\n\t* score: 0.87\n\t* });\n\t*/\n\tasync score(options) {\n\t\tconst { name, metadata, score } = options;\n\t\tlet payload;\n\t\tif (\"traceId\" in options && options.traceId) {\n\t\t\tconst formattedTraceId = isStringUUID(options.traceId) ? options.traceId : otelTraceIdToUUID(options.traceId);\n\t\t\tpayload = {\n\t\t\t\tname,\n\t\t\t\tmetadata,\n\t\t\t\tscore,\n\t\t\t\tsource: EvaluatorScoreSourceType.Code,\n\t\t\t\ttraceId: formattedTraceId\n\t\t\t};\n\t\t} else if (\"spanId\" in options && options.spanId) {\n\t\t\tconst formattedSpanId = isStringUUID(options.spanId) ? options.spanId : otelSpanIdToUUID(options.spanId);\n\t\t\tpayload = {\n\t\t\t\tname,\n\t\t\t\tmetadata,\n\t\t\t\tscore,\n\t\t\t\tsource: EvaluatorScoreSourceType.Code,\n\t\t\t\tspanId: formattedSpanId\n\t\t\t};\n\t\t} else throw new Error(\"Either 'traceId' or 'spanId' must be provided.\");\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evaluators/score\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/resources/rollout-sessions.ts\nvar RolloutSessionsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Connects to the SSE stream for rollout debugging sessions\n\t* Returns the Response object for streaming SSE events\n\t*/\n\tasync connect({ sessionId, name, params, signal }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...this.headers(),\n\t\t\t\t\"Accept\": \"text/event-stream\"\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname,\n\t\t\t\tparams\n\t\t\t}),\n\t\t\tsignal\n\t\t});\n\t\tif (!response.ok) throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);\n\t\tif (!response.body) throw new Error(\"No response body\");\n\t\treturn response;\n\t}\n\tasync delete({ sessionId }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\tasync setStatus({ sessionId, status }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/status`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({ status })\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\tasync sendSpanUpdate({ sessionId, span }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/update`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttype: \"spanStart\",\n\t\t\t\tspanId: otelSpanIdToUUID(span.spanId),\n\t\t\t\ttraceId: otelTraceIdToUUID(span.traceId),\n\t\t\t\tparentSpanId: span.parentSpanId ? otelSpanIdToUUID(span.parentSpanId) : void 0,\n\t\t\t\tattributes: span.attributes,\n\t\t\t\tstartTime: span.startTime,\n\t\t\t\tname: span.name,\n\t\t\t\tspanType: span.spanType\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/resources/sql.ts\nvar SqlResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync query(sql, parameters = {}) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/sql/query`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { ...this.headers() },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tquery: sql,\n\t\t\t\tparameters\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn (await response.json()).data;\n\t}\n};\n\n//#endregion\n//#region src/resources/tags.ts\n/** Resource for tagging traces. */\nvar TagsResource = class extends BaseResource {\n\t/** Resource for tagging traces. */\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Tag a trace with a list of tags. Note that the trace must be ended before\n\t* tagging it. You may want to call `await Laminar.flush()` after the trace\n\t* that you want to tag.\n\t*\n\t* @param {string | StringUUID} trace_id - The trace id to tag.\n\t* @param {string[] | string} tags - The tag or list of tags to add to the trace.\n\t* @returns {Promise<any>} The response from the server.\n\t* @example\n\t* ```javascript\n\t* import { Laminar, observe, LaminarClient } from \"@lmnr-ai/lmnr\";\n\t* Laminar.initialize();\n\t* const client = new LaminarClient();\n\t* let traceId: StringUUID | null = null;\n\t* // Make sure this is called outside of traced context.\n\t* await observe(\n\t* {\n\t* name: \"my-trace\",\n\t* },\n\t* async () => {\n\t* traceId = await Laminar.getTraceId();\n\t* await foo();\n\t* },\n\t* );\n\t*\n\t* // or make sure the trace is ended by this point.\n\t* await Laminar.flush();\n\t* if (traceId) {\n\t* await client.tags.tag(traceId, [\"tag1\", \"tag2\"]);\n\t* }\n\t* ```\n\t*/\n\tasync tag(trace_id, tags) {\n\t\tconst traceTags = Array.isArray(tags) ? tags : [tags];\n\t\tconst formattedTraceId = isStringUUID(trace_id) ? trace_id : otelTraceIdToUUID(trace_id);\n\t\tconst url = this.baseHttpUrl + \"/v1/tag\";\n\t\tconst payload = {\n\t\t\t\"traceId\": formattedTraceId,\n\t\t\t\"names\": traceTags\n\t\t};\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n\n//#endregion\n//#region src/index.ts\nvar LaminarClient = class {\n\tconstructor({ baseUrl, projectApiKey, port } = {}) {\n\t\tloadEnv();\n\t\tthis.projectApiKey = projectApiKey ?? process.env.LMNR_PROJECT_API_KEY;\n\t\tconst httpPort = port ?? (baseUrl?.match(/:\\d{1,5}$/g) ? parseInt(baseUrl.match(/:\\d{1,5}$/g)[0].slice(1)) : 443);\n\t\tthis.baseUrl = `${(baseUrl ?? process.env.LMNR_BASE_URL)?.replace(/\\/$/, \"\").replace(/:\\d{1,5}$/g, \"\") ?? \"https://api.lmnr.ai\"}:${httpPort}`;\n\t\tthis._browserEvents = new BrowserEventsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._datasets = new DatasetsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evals = new EvalsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evaluators = new EvaluatorsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._rolloutSessions = new RolloutSessionsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._sql = new SqlResource(this.baseUrl, this.projectApiKey);\n\t\tthis._tags = new TagsResource(this.baseUrl, this.projectApiKey);\n\t}\n\tget browserEvents() {\n\t\treturn this._browserEvents;\n\t}\n\tget datasets() {\n\t\treturn this._datasets;\n\t}\n\tget evals() {\n\t\treturn this._evals;\n\t}\n\tget evaluators() {\n\t\treturn this._evaluators;\n\t}\n\tget rolloutSessions() {\n\t\treturn this._rolloutSessions;\n\t}\n\tget sql() {\n\t\treturn this._sql;\n\t}\n\tget tags() {\n\t\treturn this._tags;\n\t}\n};\n\n//#endregion\nexport { LaminarClient };\n//# sourceMappingURL=index.mjs.map","import {\n CachedSpan,\n CacheMetadata,\n CacheServerResponse,\n} from '@lmnr-ai/types';\nimport * as http from 'http';\n\ninterface CacheServerResult {\n port: number;\n server: http.Server;\n cache: Map<string, CachedSpan>;\n setMetadata: (metadata: CacheMetadata) => void;\n}\n\nconst DEFAULT_START_PORT = 35667;\n\n/**\n * Finds an available port starting from the given port number\n */\nasync function findAvailablePort(startPort: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = http.createServer();\n\n server.listen(startPort, () => {\n const port = (server.address() as any).port;\n server.close(() => resolve(port));\n });\n\n server.on('error', (err: any) => {\n if (err.code === 'EADDRINUSE') {\n // Port is in use, try the next one\n resolve(findAvailablePort(startPort + 1));\n } else {\n reject(err as Error);\n }\n });\n });\n}\n\n/**\n * Parses request body as JSON\n */\nfunction parseBody(req: http.IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch (err) {\n reject(new Error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`));\n }\n });\n\n req.on('error', reject);\n });\n}\n\n/**\n * Starts a local cache server for storing and retrieving cached LLM responses\n * during rollout debugging sessions.\n *\n * @param startPort - Optional starting port number (defaults to 35667)\n * @returns Server information including port, server instance, cache, and metadata setter\n */\nexport async function startCacheServer(\n startPort: number = DEFAULT_START_PORT,\n): Promise<CacheServerResult> {\n const cache = new Map<string, CachedSpan>();\n let metadata: CacheMetadata = {\n pathToCount: {},\n overrides: undefined,\n };\n\n const server = http.createServer((req, res) => {\n (async () => {\n // Set CORS headers for local development\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n // Handle preflight requests\n if (req.method === 'OPTIONS') {\n res.writeHead(200);\n res.end();\n return;\n }\n\n // Health check endpoint\n if (req.method === 'GET' && req.url === '/health') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ status: 'ok' }));\n return;\n }\n\n // Cached response endpoint\n if (req.method === 'POST' && req.url === '/cached') {\n try {\n const body = await parseBody(req);\n const { path, index } = body;\n\n if (typeof path !== 'string' || typeof index !== 'number') {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(\n { error: 'Invalid request: path (string) and index (number) required' },\n ));\n return;\n }\n\n // Cache key is ${index}:${path} to handle colons in paths\n const cacheKey = `${index}:${path}`;\n const cachedSpan = cache.get(cacheKey);\n\n // Return cached span with metadata\n const response: CacheServerResponse = {\n span: cachedSpan,\n pathToCount: metadata.pathToCount,\n overrides: metadata.overrides,\n };\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(response));\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(\n { error: err instanceof Error ? err.message : String(err) },\n ));\n }\n return;\n }\n\n // 404 for unknown routes\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n })().catch((error) => {\n // Catch any unexpected errors and send 500 response\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({\n error: error instanceof Error ? error.message : 'Internal server error',\n }));\n }\n });\n });\n\n const port = await findAvailablePort(startPort);\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n resolve({\n port,\n server,\n cache,\n setMetadata: (newMetadata: CacheMetadata) => {\n metadata = newMetadata;\n },\n });\n });\n\n server.on('error', reject);\n });\n}\n","import { LaminarClient } from '@lmnr-ai/client';\nimport { RolloutHandshakeEvent, RolloutParam, RolloutRunEvent } from '@lmnr-ai/types';\nimport { EventEmitter } from 'events';\nimport { createParser } from 'eventsource-parser';\n\nconst HEARTBEAT_INTERVAL = 5000; // 5 seconds\nconst MAX_MISSED_HEARTBEATS = 3; // N missed intervals before reconnect\n\nexport interface SSEClientOptions {\n client: LaminarClient;\n sessionId: string;\n params: RolloutParam[];\n name: string;\n}\n\n/**\n * SSE client for rollout debugging sessions\n * Connects to the Laminar backend and listens for run events\n */\nexport class SSEClient extends EventEmitter {\n private client: LaminarClient;\n private sessionId: string;\n private params: RolloutParam[];\n private name: string;\n private abortController?: AbortController;\n private reconnectTimer?: NodeJS.Timeout;\n private lastHeartbeat: number = Date.now();\n private heartbeatCheckTimer?: NodeJS.Timeout;\n private isShutdown: boolean = false;\n\n constructor(options: SSEClientOptions) {\n super();\n this.client = options.client;\n this.sessionId = options.sessionId;\n this.params = options.params;\n this.name = options.name;\n }\n\n /**\n * Connects to the SSE endpoint\n */\n async connectAndListen(): Promise<void> {\n if (this.isShutdown) {\n return;\n }\n\n this.abortController = new AbortController();\n this.lastHeartbeat = Date.now();\n\n try {\n const response = await this.client.rolloutSessions.connect({\n sessionId: this.sessionId,\n params: this.params,\n signal: this.abortController.signal,\n name: this.name,\n });\n\n this.emit('connected');\n this.startHeartbeatCheck();\n\n // Parse SSE stream\n await this.parseSSEStream(response.body!);\n } catch (error: any) {\n if (error.name === 'AbortError') {\n // Connection was aborted intentionally\n return;\n }\n\n this.emit('error', error);\n\n if (!this.isShutdown) {\n // Attempt to reconnect\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Parses SSE stream and emits events\n */\n private async parseSSEStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n\n // Create SSE parser with proper event handling\n const parser = createParser({\n onEvent: (event: any) => {\n this.processSSEEvent(event);\n },\n });\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n // Feed the chunks to the parser\n const chunk = decoder.decode(value, { stream: true });\n parser.feed(chunk);\n }\n } finally {\n reader.releaseLock();\n }\n\n // Connection ended, try to reconnect if not shutdown\n if (!this.isShutdown) {\n this.scheduleReconnect();\n }\n }\n\n /**\n * Processes a parsed SSE event\n */\n private processSSEEvent(event: any): void {\n if (!event.data) {\n return;\n }\n\n try {\n // The event.event field contains the event type ('heartbeat' or 'run')\n // The event.data field contains the JSON payload\n if (event.event === 'heartbeat') {\n this.lastHeartbeat = Date.now();\n this.emit('heartbeat');\n } else if (event.event === 'run') {\n const parsedData = JSON.parse(event.data);\n const runEvent: RolloutRunEvent = {\n event_type: 'run',\n data: parsedData,\n };\n this.emit('run', runEvent);\n } else if (event.event === 'handshake') {\n const parsedData = JSON.parse(event.data);\n const handshakeEvent: RolloutHandshakeEvent = {\n event_type: 'handshake',\n data: parsedData,\n };\n this.emit('handshake', handshakeEvent);\n } else if (event.event === 'stop') {\n this.emit('stop');\n }\n } catch (error: any) {\n this.emit('error', new Error(`Failed to parse SSE event data: ${error}`));\n }\n }\n\n /**\n * Starts checking for missed heartbeats\n */\n private startHeartbeatCheck(): void {\n this.stopHeartbeatCheck();\n\n this.heartbeatCheckTimer = setInterval(() => {\n const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeat;\n const maxAllowedTime = HEARTBEAT_INTERVAL * MAX_MISSED_HEARTBEATS;\n\n if (timeSinceLastHeartbeat > maxAllowedTime) {\n this.emit('heartbeat_timeout');\n this.reconnect();\n }\n }, HEARTBEAT_INTERVAL);\n }\n\n /**\n * Stops heartbeat checking\n */\n private stopHeartbeatCheck(): void {\n if (this.heartbeatCheckTimer) {\n clearInterval(this.heartbeatCheckTimer);\n this.heartbeatCheckTimer = undefined;\n }\n }\n\n /**\n * Schedules a reconnection attempt\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer || this.isShutdown) {\n return;\n }\n\n this.emit('reconnecting');\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n this.reconnect();\n }, 1000); // Wait 1 second before reconnecting\n }\n\n /**\n * Reconnects to the SSE endpoint\n */\n private reconnect(): void {\n this.disconnect(true);\n this.connectAndListen().catch(error => {\n this.emit('error', error);\n });\n }\n\n /**\n * Disconnects from the SSE endpoint\n */\n private disconnect(stopReconnect: boolean = true): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = undefined;\n }\n\n this.stopHeartbeatCheck();\n\n if (stopReconnect && this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n }\n\n /**\n * Updates the function metadata (params, name) and reconnects\n */\n updateMetadata(params: RolloutParam[], name: string): void {\n this.params = params;\n this.name = name;\n\n // Reconnect to send updated metadata\n this.reconnect();\n }\n\n /**\n * Shuts down the SSE client gracefully\n */\n shutdown(): void {\n this.isShutdown = true;\n this.disconnect(true);\n this.emit('shutdown');\n this.removeAllListeners();\n }\n}\n\n/**\n * Creates an SSE client (does not auto-connect)\n * Call client.connect() after registering event listeners\n */\nexport function createSSEClient(options: SSEClientOptions): SSEClient {\n return new SSEClient(options);\n}\n","//#region src/tracing.ts\n/**\n* Tracing levels to conditionally disable tracing.\n*\n* OFF - No tracing is sent.\n* META_ONLY - Only metadata is sent (e.g. tokens, costs, etc.).\n* ALL - All data is sent.\n*/\nlet TracingLevel = /* @__PURE__ */ function(TracingLevel$1) {\n\tTracingLevel$1[\"OFF\"] = \"off\";\n\tTracingLevel$1[\"META_ONLY\"] = \"meta_only\";\n\tTracingLevel$1[\"ALL\"] = \"all\";\n\treturn TracingLevel$1;\n}({});\n\n//#endregion\n//#region src/worker-protocol.ts\n/**\n* Message prefix for protocol messages in stdout\n*/\nconst WORKER_MESSAGE_PREFIX = \"__LMNR_WORKER__:\";\n\n//#endregion\nexport { TracingLevel, WORKER_MESSAGE_PREFIX };\n//# sourceMappingURL=index.mjs.map","import pino, { Level } from 'pino';\nimport { PinoPretty } from 'pino-pretty';\n\nexport function initializeLogger(options?: { colorize?: boolean; level?: Level }) {\n const colorize = options?.colorize ?? true;\n const level =\n options?.level ??\n (process.env.LMNR_LOG_LEVEL?.toLowerCase()?.trim() as Level) ??\n 'info';\n\n return pino(\n {\n level,\n },\n PinoPretty({\n colorize,\n minimumLevel: level,\n }),\n );\n}\n","import { WORKER_MESSAGE_PREFIX, WorkerConfig, WorkerMessage } from '@lmnr-ai/types';\nimport { ChildProcess, spawn } from 'child_process';\nimport * as readline from 'readline';\n\nimport { initializeLogger } from '../utils';\n\nconst logger = initializeLogger();\n\nexport interface ExecuteOptions {\n command: string;\n args: string[];\n config: WorkerConfig;\n}\n\n/**\n * Track and kill the currently running subprocess\n */\nexport class SubprocessManager {\n private currentProcess: ChildProcess | null = null;\n\n /**\n * Execute a subprocess and track it\n */\n async execute(options: ExecuteOptions): Promise<any> {\n const { command, args, config } = options;\n\n // Spawn the worker process\n const child: ChildProcess = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n this.currentProcess = child;\n\n return new Promise((resolve, reject) => {\n let result: any = undefined;\n let hasError = false;\n\n // Set up readline interface for stdout\n const rl = readline.createInterface({\n input: child.stdout!,\n crlfDelay: Infinity,\n });\n\n // Handle messages from worker\n rl.on('line', (line: string) => {\n // Check if this is a worker protocol message or user output\n if (line.startsWith(WORKER_MESSAGE_PREFIX)) {\n // Parse worker protocol message\n try {\n const messageJson = line.substring(WORKER_MESSAGE_PREFIX.length);\n const message: WorkerMessage = JSON.parse(messageJson);\n\n switch (message.type) {\n // wrapped in a block for const not to be hoisted\n case 'log': {\n // Forward log messages through pino logger\n logger[message.level](message.message);\n break;\n }\n case 'result':\n result = message.data;\n break;\n\n case 'error':\n hasError = true;\n logger.error(`Worker error: ${message.error}`);\n if (message.stack) {\n logger.error(message.stack);\n }\n break;\n }\n } catch {\n logger.error(`Failed to parse worker protocol message: ${line}`);\n }\n } else {\n // This is user output from console.log - pass it through transparently\n console.log(line);\n }\n });\n\n // Pass through stderr for user's console.error\n child.stderr!.on('data', (data: Buffer) => {\n process.stderr.write(data);\n });\n\n // Handle process exit\n child.on('exit', (code: number | null, signal: string | null) => {\n if (this.currentProcess?.pid === child.pid) {\n this.currentProcess = null;\n }\n\n if (signal) {\n reject(new Error(`Worker terminated by signal: ${signal}`));\n } else if (code === 0) {\n resolve(result);\n } else {\n if (!hasError) {\n logger.error(`Worker exited with code ${code}`);\n }\n reject(new Error(`Worker exited with code ${code}`));\n }\n });\n\n // Handle spawn errors\n child.on('error', (error: Error) => {\n this.currentProcess = null;\n reject(new Error(`Failed to spawn worker: ${error.message}`));\n });\n\n // Send configuration to worker via stdin\n child.stdin?.write(JSON.stringify(config) + '\\n');\n child.stdin?.end();\n });\n }\n\n /**\n * Kill the currently running subprocess\n */\n kill(): void {\n if (this.currentProcess) {\n const processToKill = this.currentProcess;\n this.currentProcess.kill('SIGTERM');\n\n // Fallback to SIGKILL after 5 seconds\n setTimeout(() => {\n // exitCode is null if the process is still running\n if (processToKill && processToKill.exitCode === null) {\n logger.warn('Child process did not terminate, using SIGKILL');\n processToKill.kill('SIGKILL');\n }\n }, 5000);\n }\n }\n\n /**\n * Check if a subprocess is currently running\n */\n isRunning(): boolean {\n return this.currentProcess !== null;\n }\n}\n","import * as path from 'path';\n\nexport interface WorkerCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Default workers mapped by file extension\n */\nconst DEFAULT_WORKERS: Record<string, WorkerCommand> = {\n '.ts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.cts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.mts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.tsx': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.jsx': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.js': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.mjs': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.cjs': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.py': {\n command: 'python3',\n args: ['-m', 'lmnr.cli.worker'],\n },\n};\n\n/**\n * Get the worker command for a given file path or module.\n * Resolves the TypeScript worker dynamically from @lmnr-ai/lmnr package.\n */\nexport function getWorkerCommand(\n filePath?: string,\n options?: { pythonModule?: string },\n): WorkerCommand {\n // If Python module mode, always use Python worker\n if (options?.pythonModule) {\n return {\n command: 'python3',\n args: ['-m', 'lmnr.cli.worker'],\n };\n }\n\n // Otherwise determine by file extension\n if (!filePath) {\n throw new Error('Either filePath or pythonModule must be provided');\n }\n\n const ext = path.extname(filePath);\n\n if (!DEFAULT_WORKERS[ext]) {\n throw new Error(\n `Unsupported file extension: ${ext}. ` +\n `Supported extensions: ${Object.keys(DEFAULT_WORKERS).join(', ')}`,\n );\n }\n\n const worker = DEFAULT_WORKERS[ext];\n\n // For TypeScript/JavaScript files, resolve the worker from @lmnr-ai/lmnr\n if (['.ts', '.tsx', '.js', '.mjs', '.cjs', '.mts', '.cts', '.jsx'].includes(ext)) {\n try {\n // Try to resolve the worker from @lmnr-ai/lmnr package\n const workerPath = require.resolve('@lmnr-ai/lmnr/dist/cli/worker/index.cjs');\n return {\n command: worker.command,\n args: [workerPath],\n };\n } catch (error) {\n throw new Error(\n 'Failed to resolve TypeScript/JavaScript worker from @lmnr-ai/lmnr package. ' +\n 'Make sure @lmnr-ai/lmnr is installed. ' +\n `Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return worker;\n}\n\n/**\n * Get a custom worker command with overrides.\n * Allows users to specify custom commands via CLI flags.\n */\nexport function getCustomWorkerCommand(\n command: string,\n args: string[],\n): WorkerCommand {\n return { command, args };\n}\n","import { LaminarClient } from '@lmnr-ai/client';\nimport {\n type CachedSpan,\n type RolloutHandshakeEvent,\n type RolloutParam,\n type RolloutRunEvent,\n type WorkerConfig,\n} from '@lmnr-ai/types';\nimport chokidar from 'chokidar';\nimport * as path from 'path';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { startCacheServer } from '../cache-server';\nimport { createSSEClient, SSEClient } from '../sse-client';\nimport { SubprocessManager } from '../subprocess/executor';\nimport { initializeLogger } from '../utils';\nimport { getWorkerCommand } from '../worker-registry';\n\ninterface FunctionMetadata {\n name: string; // The span name from observe({ name: '...' })\n exportName: string; // The actual export/variable name\n params: RolloutParam[];\n}\n\nconst logger = initializeLogger();\n\n// Extensions that use TypeScript/JavaScript build and runtime discovery\nconst TS_JS_EXTENSIONS = [\n '.ts',\n '.tsx',\n '.js',\n '.mjs',\n '.cjs',\n '.jsx',\n '.mts',\n '.cts',\n];\n\n// All extensions that support metadata discovery\nconst EXTENSIONS_TO_DISCOVER_METADATA = [...TS_JS_EXTENSIONS, '.py'];\n\nexport interface DevOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n grpcPort?: number;\n function?: string;\n frontendPort?: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n command?: string;\n commandArgs?: string[];\n pythonModule?: string; // Python module path (e.g., 'src.myfile')\n}\n\ninterface DiscoveredMetadata {\n functionName: string;\n params: RolloutParam[];\n}\n\nconst logLmnrPackageNotFoundAndExit = () => {\n logger.error(\n '@lmnr-ai/lmnr package not found or outdated. ' +\n 'For JS/TS projects, please install the latest version of @lmnr-ai/lmnr in your project: ' +\n 'npm install @lmnr-ai/lmnr\\n' +\n 'You might need to run `lmnr-cli` from the root of your project',\n );\n process.exit(1);\n};\n\n/**\n * Discovers function metadata for TypeScript and JavaScript files by:\n * 1. Extracting TypeScript metadata (params with types from source - TS only)\n * 2. Building and loading the module with esbuild\n * 3. Selecting the appropriate function\n * 4. Matching metadata by span name\n *\n * For JavaScript files, TypeScript metadata extraction fails gracefully, but runtime\n * parameter extraction via regex still works (param names without types).\n */\nconst discoverTypeScriptMetadata = async (\n filePath: string,\n options: { function?: string; externalPackages?: string[]; dynamicImportsToSkip?: string[] },\n): Promise<DiscoveredMetadata> => {\n let extractRolloutFunctions: any;\n let buildFile: any;\n let loadModule: any;\n let selectRolloutFunction: any;\n\n try {\n /* eslint-disable @typescript-eslint/no-require-imports */\n // Use dynamic require to prevent bundler from trying to resolve at build time\n const lmnrPackage = '@lmnr-ai/lmnr';\n const tsParserPath = require.resolve(`${lmnrPackage}/dist/cli/worker/ts-parser.cjs`);\n const buildModulePath = require.resolve(`${lmnrPackage}/dist/cli/worker/build.cjs`);\n\n // Clear require cache to ensure we get fresh modules on reload\n delete require.cache[tsParserPath];\n delete require.cache[buildModulePath];\n\n extractRolloutFunctions = require(tsParserPath).extractRolloutFunctions;\n const buildModule = require(buildModulePath);\n buildFile = buildModule.buildFile;\n loadModule = buildModule.loadModule;\n selectRolloutFunction = buildModule.selectRolloutFunction;\n /* eslint-enable @typescript-eslint/no-require-imports */\n\n if (!extractRolloutFunctions || !buildFile || !loadModule || !selectRolloutFunction) {\n logger.error(\n \"Missing exports from @lmnr-ai/lmnr modules. \" +\n \"This may indicate an outdated package version.\",\n );\n logLmnrPackageNotFoundAndExit();\n }\n } catch (error: any) {\n if (error.code === 'MODULE_NOT_FOUND') {\n logLmnrPackageNotFoundAndExit();\n }\n // Re-throw any other errors (syntax errors, etc.)\n logger.error(`Unexpected error loading @lmnr-ai/lmnr modules: ${error.message}`);\n throw error;\n }\n\n\n // Extract TypeScript metadata\n let paramsMetadata: Map<string, FunctionMetadata> | undefined;\n try {\n paramsMetadata = extractRolloutFunctions(filePath);\n logger.debug(`Extracted TypeScript metadata for ${paramsMetadata?.size} functions`);\n } catch (error) {\n logger.warn(\n 'Failed to extract TypeScript metadata, falling back to runtime parsing: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n }\n\n // Build and load the module\n const moduleText = await buildFile(filePath, {\n externalPackages: options.externalPackages,\n dynamicImportsToSkip: options.dynamicImportsToSkip,\n });\n loadModule({\n filename: filePath,\n moduleText,\n });\n\n // Select the appropriate function\n const selectedFunction = selectRolloutFunction(options.function);\n\n // If we have TypeScript metadata, match by span name and enrich params\n if (paramsMetadata) {\n logger.debug(`Available TS metadata keys: ${Array.from(paramsMetadata.keys()).join(', ')}`);\n logger.debug(\n `Looking for span name: ${selectedFunction.name} ` +\n `(runtime key: ${selectedFunction.exportName})`,\n );\n\n // Search for metadata by span name\n let foundMetadata: FunctionMetadata | null = null;\n for (const [exportName, metadata] of paramsMetadata.entries()) {\n logger.debug(\n `Checking ${exportName}: span name = ${metadata.name}, export name = ${exportName}`,\n );\n if (metadata.name === selectedFunction.name) {\n foundMetadata = metadata;\n logger.debug(`Match. Export name: ${exportName}, span name: ${metadata.name}`);\n break;\n }\n }\n\n if (foundMetadata) {\n selectedFunction.params = foundMetadata.params;\n logger.debug(`Using TypeScript metadata for span: ${selectedFunction.name}`);\n } else {\n logger.info(`No TypeScript metadata found for span name: ${selectedFunction.name}`);\n }\n }\n\n return {\n functionName: selectedFunction.name,\n params: selectedFunction.params || [],\n };\n};\n\n/**\n * Helper to execute subprocess commands\n */\nconst execCommand = async (\n command: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> => new Promise((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { spawn } = require('child_process');\n const child = spawn(command, args);\n let stdout = '';\n let stderr = '';\n\n child.stdout.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on('close', (code: number | null) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n } else {\n reject(new Error(`Command failed with code ${code}: ${stderr}`));\n }\n });\n\n child.on('error', (error: Error) => {\n reject(error);\n });\n});\n\n/**\n * Protocol prefix for metadata discovery responses\n * This allows us to safely parse JSON even if there are other log statements in stdout\n */\nexport const METADATA_PROTOCOL_PREFIX = 'LMNR_METADATA:';\n\n/**\n * Extracts JSON metadata from stdout that may contain other log statements\n * Looks for lines matching the protocol prefix and parses the JSON payload\n *\n * @param stdout - Raw stdout output that may contain logs and metadata\n * @returns Parsed JSON object\n * @throws Error if no valid metadata line is found or JSON parsing fails\n */\nexport const extractMetadataFromStdout = (stdout: string): any => {\n // Find all positions where LMNR_METADATA: appears\n const prefixPositions: number[] = [];\n let searchStart = 0;\n while (true) {\n const pos = stdout.indexOf(METADATA_PROTOCOL_PREFIX, searchStart);\n if (pos === -1) break;\n prefixPositions.push(pos);\n searchStart = pos + METADATA_PROTOCOL_PREFIX.length;\n }\n\n if (prefixPositions.length === 0) {\n // Fallback: try parsing the entire stdout as JSON (backward compatibility)\n try {\n return JSON.parse(stdout.trim());\n } catch {\n throw new Error(\n \"No metadata found in output. \" +\n \"Please make sure you are running the latest version of `lmnr` python package.\",\n );\n }\n }\n\n // Try to parse JSON starting from each prefix position\n // We'll keep the last successfully parsed JSON\n let lastValidJson: any = null;\n\n for (const pos of prefixPositions) {\n // Start after the prefix\n const startPos = pos + METADATA_PROTOCOL_PREFIX.length;\n const jsonText = stdout.slice(startPos).trim();\n\n // Try to parse the JSON by attempting increasingly shorter substrings\n // Strategy: Look for the end of the JSON object/array by finding matching braces\n // This handles the case where there might be additional text after the JSON\n\n // First, try parsing to the next newline (most common case)\n const nextNewline = stdout.indexOf('\\n', startPos);\n if (nextNewline !== -1) {\n const lineText = stdout.slice(startPos, nextNewline).trim();\n try {\n lastValidJson = JSON.parse(lineText);\n continue;\n } catch {\n // If that fails, we'll try the more complex approach below\n }\n }\n\n // More complex case: try to find the end of the JSON by counting braces\n // This handles multi-line JSON or JSON followed by more text\n try {\n let depth = 0;\n let inString = false;\n let escapeNext = false;\n let firstChar = -1;\n\n for (let i = 0; i < jsonText.length; i++) {\n const char = jsonText[i];\n\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\' && inString) {\n escapeNext = true;\n continue;\n }\n\n if (char === '\"') {\n inString = !inString;\n continue;\n }\n\n if (inString) continue;\n\n if (char === '{' || char === '[') {\n if (firstChar === -1) firstChar = i;\n depth++;\n } else if (char === '}' || char === ']') {\n depth--;\n if (depth === 0 && firstChar !== -1) {\n // Found the end of the JSON object/array\n const candidate = jsonText.slice(0, i + 1);\n lastValidJson = JSON.parse(candidate);\n break;\n }\n }\n }\n\n // If we didn't find a complete object, try parsing the whole thing\n if (depth !== 0 || firstChar === -1) {\n lastValidJson = JSON.parse(jsonText);\n }\n } catch {\n // If parsing fails, continue to the next prefix position\n continue;\n }\n }\n\n if (lastValidJson === null) {\n throw new Error(\n \"No valid metadata JSON found in output. \" +\n \"Please make sure you are running the latest version of `lmnr` python package.\",\n );\n }\n\n return lastValidJson;\n};\n\n/**\n * Discovers function metadata for Python files/modules by calling the lmnr Python CLI\n */\nconst discoverPythonMetadata = async (\n filePathOrModule: string,\n options: DevOptions,\n): Promise<DiscoveredMetadata> => {\n logger.debug(`Discovering Python metadata for ${filePathOrModule}`);\n const args = ['discover'];\n\n // Determine if we're using a file path or module\n if (options.pythonModule) {\n // Module mode: lmnr discover --module src.myfile\n args.push('--module', options.pythonModule);\n } else {\n // Script mode: lmnr discover --file src/myfile.py\n args.push('--file', filePathOrModule);\n }\n\n // Add optional function name\n if (options.function) {\n args.push('--function', options.function);\n }\n\n try {\n // Execute: lmnr discover --file <path> | --module <module> [--function <name>]\n const result = await execCommand('lmnr', args);\n const response = extractMetadataFromStdout(result.stdout);\n\n // Response format: { \"name\": \"...\", \"params\": [...] }\n return {\n functionName: response.name,\n params: response.params || [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to discover Python metadata: ${errorMessage}`);\n if (errorMessage.toLowerCase().includes('command not found') ||\n errorMessage.includes('spawn lmnr ENOENT')) {\n logger.info(\n \"HINT: Make sure latest version of `lmnr` python package is installed. \" +\n \"`pip install --upgrade lmnr`, or if you are running this command from a virtual \" +\n \"environment, make sure to activate it. For `uv` users, rerun the command with `uv run`, \" +\n `e.g. \"uv run npx lmnr-cli dev ${filePathOrModule}\"`,\n );\n process.exit(1);\n }\n // Fallback\n const defaultName = options.pythonModule\n ? options.pythonModule.split('.').pop() || 'main'\n : path.basename(filePathOrModule, '.py');\n return {\n functionName: options.function || defaultName,\n params: [],\n };\n }\n};\n\n/**\n * Generic metadata discovery dispatcher that routes to language-specific implementations\n */\nconst discoverFunctionMetadata = async (\n filePathOrModule: string,\n options: DevOptions,\n): Promise<DiscoveredMetadata> => {\n // If pythonModule is set, we're in Python module mode\n if (options.pythonModule) {\n return await discoverPythonMetadata(filePathOrModule, options);\n }\n\n // Otherwise check file extension\n const ext = path.extname(filePathOrModule);\n\n // TypeScript and JavaScript files use the same build/load/select process\n // For JS files, TypeScript metadata extraction will fail, but runtime param extraction works\n if (TS_JS_EXTENSIONS.includes(ext)) {\n return await discoverTypeScriptMetadata(filePathOrModule, options);\n }\n\n if (ext === '.py') {\n return await discoverPythonMetadata(filePathOrModule, options);\n }\n\n // Fallback for unsupported file types\n logger.warn(`No metadata discovery available for ${ext} files`);\n return {\n functionName: options.function || path.basename(filePathOrModule, ext),\n params: [],\n };\n};\n\nfunction newUUID(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return uuidv4();\n}\n\nfunction getFrontendUrl(baseUrl?: string, frontendPort?: number): string {\n let url = baseUrl ?? 'https://api.lmnr.ai';\n if (url === 'https://api.lmnr.ai') {\n url = 'https://www.laminar.sh';\n }\n url = url.replace(/\\/$/, '');\n\n if (/localhost|127\\.0\\.0\\.1/.test(url)) {\n const port = frontendPort ?? url.match(/:\\d{1,5}$/g)?.[0]?.slice(1) ?? 5667;\n url = url.replace(/:\\d{1,5}$/g, '');\n return `${url}:${port}`;\n }\n\n return url;\n}\n\n/**\n * Parses request arguments, attempting JSON parse for strings\n */\nconst tryParseArg = (arg: unknown) => {\n if (typeof arg === 'string') {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(arg);\n } catch {\n return arg;\n }\n }\n return arg;\n};\n\n/**\n * Handles a run event from the backend\n */\nconst handleRunEvent = async (\n event: RolloutRunEvent,\n sessionId: string,\n filePathOrModule: string,\n client: LaminarClient,\n cacheServerPort: number,\n cache: Map<string, CachedSpan>,\n setMetadata: (metadata: any) => void,\n options: DevOptions,\n subprocessManager: SubprocessManager,\n): Promise<void> => {\n logger.debug('Received run event');\n\n const { trace_id, path_to_count, args: rawArgs, overrides } = event.data;\n\n const parsedArgs = Array.isArray(rawArgs)\n ? rawArgs.map(tryParseArg)\n : (Object.fromEntries(\n Object.entries(rawArgs).map(([key, value]) => [key, tryParseArg(value)]),\n ) as Record<string, any>);\n\n cache.clear();\n setMetadata({\n pathToCount: {},\n overrides: overrides,\n });\n\n try {\n // Check if we should populate cache from a previous trace\n if (!trace_id || trace_id.trim() === '') {\n logger.info('No spans in cache, starting fresh');\n } else {\n // Query spans from the backend to populate cache\n const paths = Object.keys(path_to_count || {});\n if (paths.length === 0) {\n logger.info('No spans to cache, starting fresh');\n } else {\n const query = `\n SELECT name, input, output, attributes, path\n FROM spans\n WHERE trace_id = {traceId:UUID}\n AND path IN {paths:String[]}\n ORDER BY start_time ASC\n `;\n\n logger.debug(`Querying spans from trace ${trace_id}...`);\n const spans = await client.sql.query(query, {\n traceId: trace_id,\n paths: paths,\n });\n logger.debug(`Received ${spans.length} spans from backend`);\n\n // Group spans by path and filter to first N per path\n const spansByPath: Record<string, any[]> = {};\n for (const span of spans) {\n const path = span.path as string;\n if (!spansByPath[path]) {\n spansByPath[path] = [];\n }\n spansByPath[path].push(span);\n }\n\n for (const [path, pathSpans] of Object.entries(spansByPath)) {\n const maxCount = path_to_count?.[path] || 0;\n const spansToCache = pathSpans.slice(0, maxCount);\n\n spansToCache.forEach((span, index) => {\n // Parse JSON fields\n let parsedInput = span.input;\n let parsedOutput = span.output;\n let parsedAttributes = span.attributes;\n\n try {\n parsedInput =\n typeof span.input === 'string' ? JSON.parse(span.input) : span.input;\n } catch {\n // Keep as string\n }\n\n try {\n parsedOutput =\n typeof span.output === 'string' ? span.output : JSON.stringify(span.output);\n } catch {\n parsedOutput = String(span.output);\n }\n\n try {\n parsedAttributes =\n typeof span.attributes === 'string'\n ? JSON.parse(span.attributes)\n : span.attributes;\n } catch {\n parsedAttributes = {};\n }\n\n const cachedSpan: CachedSpan = {\n name: span.name,\n input: parsedInput,\n output: parsedOutput,\n attributes: parsedAttributes,\n };\n\n const cacheKey = `${index}:${path}`;\n cache.set(cacheKey, cachedSpan);\n });\n\n logger.info(`Cached ${spansToCache.length} spans for path: ${path}`);\n }\n\n // Store metadata in cache server\n setMetadata({\n pathToCount: path_to_count || {},\n overrides,\n });\n }\n }\n\n // Parse baseUrl similar to how evaluations does it\n const baseUrl = options.baseUrl ?? process.env.LMNR_BASE_URL ?? 'https://api.lmnr.ai';\n const httpPort =\n options.port ??\n (baseUrl.match(/:\\d{1,5}$/g)\n ? parseInt(baseUrl.match(/:\\d{1,5}$/g)![0].slice(1))\n : 443);\n const grpcPort = options.grpcPort ?? 8443;\n\n // Prepare environment variables for child process\n const env: Record<string, string> = {\n LMNR_ROLLOUT_SESSION_ID: sessionId,\n LMNR_ROLLOUT_STATE_SERVER_ADDRESS: `http://localhost:${cacheServerPort}`,\n };\n\n // Prepare worker configuration\n const workerConfig: WorkerConfig = {\n filePath: options.pythonModule ? undefined : filePathOrModule,\n modulePath: options.pythonModule,\n functionName: options.function,\n args: parsedArgs,\n env,\n cacheServerPort,\n baseUrl,\n projectApiKey: options.projectApiKey,\n httpPort,\n grpcPort,\n externalPackages: options.externalPackages,\n dynamicImportsToSkip: options.dynamicImportsToSkip,\n };\n\n // Get worker command\n const workerCommand = options.command\n ? { command: options.command, args: options.commandArgs ?? [] }\n : getWorkerCommand(options.pythonModule ? undefined : filePathOrModule, options);\n\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'RUNNING',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n\n // Execute the rollout function in subprocess\n await subprocessManager.execute({\n command: workerCommand.command,\n args: workerCommand.args,\n config: workerConfig,\n });\n\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'FINISHED',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n } catch (error: any) {\n logger.error(`Error handling run event: ${error instanceof Error ? error.message : error}`);\n if (error instanceof Error && error.stack) {\n logger.error(error.stack);\n }\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'FINISHED',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n }\n};\n\n/**\n * Main dev command handler\n */\nexport async function runDev(filePath?: string, options: DevOptions = {}): Promise<void> {\n // Determine the actual path/module to use\n const isPythonModule = !!options.pythonModule;\n const filePathOrModule = filePath || options.pythonModule!;\n let didLogHandshake = false;\n\n // Generate session ID\n const sessionId = newUUID();\n\n // Initialize Laminar client\n const client = new LaminarClient({\n baseUrl: options.baseUrl,\n projectApiKey: options.projectApiKey,\n port: options.port,\n });\n\n // Start cache server\n logger.debug('Starting cache server...');\n const { port: cacheServerPort, server: cacheServer, cache, setMetadata } =\n await startCacheServer();\n logger.debug(`Cache server started on port ${cacheServerPort}`);\n\n // Create subprocess manager\n const subprocessManager = new SubprocessManager();\n\n // Get function metadata (name and params)\n let functionName = options.function;\n let params: RolloutParam[] = [];\n\n try {\n // Check if we should discover metadata\n const shouldDiscover =\n isPythonModule ||\n (filePath && EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath)));\n\n if (shouldDiscover) {\n logger.debug('Discovering rollout functions...');\n const metadata = await discoverFunctionMetadata(filePathOrModule, options);\n functionName = metadata.functionName;\n params = metadata.params;\n\n logger.info(`Serving function: ${functionName}`);\n logger.debug(`Function parameters: ${JSON.stringify(params, null, 2)}`);\n } else if (filePath) {\n // Unsupported file type\n functionName = options.function || path.basename(filePath, path.extname(filePath));\n logger.warn(`Metadata discovery not available for ${path.extname(filePath)} files`);\n }\n } catch (error) {\n logger.error(\n 'Failed to discover rollout functions: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n cacheServer.close();\n throw error;\n }\n\n // Setup file watcher for hot reload\n logger.debug('Setting up file watcher...');\n const watcher = chokidar.watch('.', {\n ignored: (path: string) => {\n const ignoredDirs = [\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n 'coverage',\n '.turbo',\n 'tmp',\n 'temp',\n 'venv',\n '.venv',\n 'virtualenv',\n '.virtualenv',\n '__pycache__',\n '.pytest_cache',\n '.ruff_cache',\n '.mypy_cache',\n '.cache',\n '.DS_Store',\n ];\n\n const pathSegments = path.split(/[/\\\\]/);\n if (pathSegments.some((segment) => ignoredDirs.includes(segment))) {\n return true;\n }\n\n if (path.endsWith('.log') || path.endsWith('.map')) {\n return true;\n }\n\n return false;\n },\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 100,\n },\n });\n\n // Create SSE client\n logger.debug('Setting up SSE client...');\n let sseClient: SSEClient | null = null;\n\n try {\n sseClient = createSSEClient({\n client,\n sessionId,\n params: params,\n name: functionName ?? '',\n });\n\n // Register all event listeners BEFORE connecting\n sseClient.on('heartbeat', () => {\n logger.debug('Heartbeat received');\n });\n\n sseClient.on('run', (event: RolloutRunEvent) => {\n if (subprocessManager.isRunning()) {\n logger.warn('Rollout is already running, skipping new run');\n return;\n }\n\n handleRunEvent(\n event,\n sessionId,\n filePathOrModule,\n client,\n cacheServerPort,\n cache,\n setMetadata,\n options,\n subprocessManager,\n ).catch((error) => {\n logger.error(\n 'Unhandled error in run event handler: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n });\n });\n\n sseClient.on('handshake', (event: RolloutHandshakeEvent) => {\n const projectId = event.data.project_id;\n const sessionId = event.data.session_id;\n const frontendUrl = getFrontendUrl(options.baseUrl, options.frontendPort);\n if (!didLogHandshake) {\n logger.info(\n `View your session at ${frontendUrl}/project/${projectId}/rollout-sessions/${sessionId}`,\n );\n }\n didLogHandshake = true;\n });\n\n sseClient.on('error', (error: Error) => {\n logger.warn(`Error connecting to backend: ${error.message}`);\n });\n\n sseClient.on('reconnecting', () => {\n logger.info('Reconnecting to backend...');\n });\n\n sseClient.on('heartbeat_timeout', () => {\n logger.debug('Heartbeat timeout, reconnecting...');\n });\n\n sseClient.on('stop', () => {\n logger.debug('Cancelling current run...');\n subprocessManager.kill();\n logger.info('Current run cancelled');\n });\n\n // Setup file change handler for hot reload with debouncing\n let reloadTimeout: NodeJS.Timeout | null = null;\n watcher.on('change', (changedPath: string) => {\n logger.info(`File changed: ${changedPath}, reloading...`);\n\n // Clear any pending reload\n if (reloadTimeout) {\n clearTimeout(reloadTimeout);\n }\n\n // Cancel running subprocess immediately\n if (subprocessManager.isRunning()) {\n logger.warn('Cancelling current run due to file change');\n subprocessManager.kill();\n }\n\n // Debounce the reload to avoid reading partial file writes\n reloadTimeout = setTimeout(() => {\n logger.debug('Executing debounced reload...');\n reloadTimeout = null;\n\n // Re-discover function metadata for supported file types\n if (\n isPythonModule ||\n (filePath &&\n EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath)))\n ) {\n discoverFunctionMetadata(filePathOrModule, options)\n .then((metadata) => {\n logger.debug(`Updated function metadata: ${metadata.functionName}`);\n logger.debug(`Updated parameters: ${JSON.stringify(metadata.params, null, 2)}`);\n\n // Update the SSE client with new metadata\n if (sseClient) {\n sseClient.updateMetadata(metadata.params, metadata.functionName);\n logger.debug('Notified backend of metadata changes');\n }\n })\n .catch((error: any) => {\n logger.error(\n 'Failed to update function metadata: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n if (error instanceof Error && error.stack) {\n logger.debug(`Stack trace: ${error.stack}`);\n }\n });\n }\n }, 100); // Wait 100ms after the last change before reloading\n });\n\n // Handle graceful shutdown\n const shutdown = () => {\n logger.debug('Shutting down...');\n\n // Clear any pending reload timeout\n if (reloadTimeout) {\n clearTimeout(reloadTimeout);\n reloadTimeout = null;\n }\n\n // Close file watcher\n logger.debug('Closing file watcher...');\n watcher\n .close()\n .catch((error: any) => {\n logger.error(\n `Failed to close file watcher: ${error instanceof Error ? error.message : error}`,\n );\n });\n\n // Kill any running subprocess\n subprocessManager.kill();\n\n // Delete the rollout session\n logger.debug('Deleting rollout session...');\n client.rolloutSessions\n .delete({ sessionId })\n .then(() => {\n if (sseClient) {\n sseClient.shutdown();\n }\n\n cacheServer.close(() => {\n logger.debug('Cache server closed');\n });\n process.exit(0);\n })\n .catch((error: any) => {\n logger.warn(\n `Failed to delete rollout session: ${error instanceof Error ? error.message : error}`,\n );\n process.exit(1);\n });\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n // Keep stdin open to prevent process from exiting\n process.stdin.resume();\n\n // Connect to backend and start listening\n logger.debug('Connecting to backend...');\n await sseClient.connectAndListen();\n } catch (error) {\n logger.error(\n 'Failed to start dev command: ' + (error instanceof Error ? error.message : String(error)),\n );\n\n // Try to delete the rollout session before exiting\n try {\n await client.rolloutSessions.delete({ sessionId });\n } catch {\n // Ignore delete errors during error cleanup\n }\n\n await watcher.close();\n cacheServer.close(() => {\n process.exit(1);\n });\n }\n}\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\n\nimport { version } from '../package.json';\nimport { runDev } from './commands/dev';\n\nasync function main() {\n const program = new Command();\n\n program\n .name('lmnr-cli')\n .description('CLI for Laminar AI rollout debugging')\n .version(version, '-v, --version', 'display version number');\n\n program\n .command('dev')\n .description('Start a rollout debugging session')\n .argument(\n '[file]',\n 'Path to file containing the agent function(s). Either `file` or `-m` must be provided.',\n )\n .option(\n '-m, --python-module <module>',\n 'Python module path (e.g., src.myfile). Either `file` or `-m` must be provided.',\n )\n .option(\n '--function <name>',\n 'Specific function to serve (if multiple rollout functions found)',\n )\n .option(\n '--project-api-key <key>',\n 'Project API key. If not provided, reads from LMNR_PROJECT_API_KEY env variable',\n )\n .option(\n '--base-url <url>',\n 'Base URL for the Laminar API. Defaults to https://api.lmnr.ai or LMNR_BASE_URL env variable',\n )\n .option('--port <port>', 'Port for the Laminar API. Defaults to 443', (val) =>\n parseInt(val, 10),\n )\n .option(\n '--grpc-port <port>',\n 'Port for the Laminar gRPC backend. Defaults to 8443',\n (val) => parseInt(val, 10),\n )\n .option(\n '--frontend-port <port>',\n 'Port for the Laminar frontend. Defaults to 5667',\n (val) => parseInt(val, 10),\n )\n .option(\n '--external-packages <packages...>',\n '[ADVANCED] List of packages to pass as external to esbuild. This will not link ' +\n 'the packages directly into the dev file, but will instead require them at runtime. ' +\n 'Read more: https://esbuild.github.io/api/#external',\n )\n .option(\n '--dynamic-imports-to-skip <modules...>',\n '[ADVANCED] List of module names to skip when encountered as dynamic imports. ' +\n 'These dynamic imports will resolve to an empty module to prevent build failures. ' +\n 'This is meant to skip the imports that are not used in the rollout itself.',\n )\n .option(\n '--command <command>',\n '[ADVANCED] Custom command to run the worker (e.g., python3, node)',\n )\n .option(\n '--command-args <args...>',\n '[ADVANCED] Arguments for the custom command',\n )\n .action(async (file: string | undefined, options) => {\n // Validation: must have either file or python-module, but not both\n if (!file && !options.pythonModule) {\n console.error('Error: Must provide either a file path or --python-module (-m) flag');\n process.exit(1);\n }\n if (file && options.pythonModule) {\n console.error('Error: Cannot specify both file path and --python-module (-m) flag');\n process.exit(1);\n }\n\n await runDev(file, options);\n })\n .addHelpText(\n 'after',\n `\nExamples:\n $ lmnr-cli dev agent.ts # TypeScript file\n $ lmnr-cli dev agent.py # Python file (script mode)\n $ lmnr-cli dev -m src.agent # Python module (module mode)\n $ lmnr-cli dev agent.ts --function myAgent # Specific function\n`,\n );\n\n await program.parseAsync();\n}\n\nmain().catch((err) => {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n});\n"],"x_google_ignoreList":[1,2],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["path","crypto","initializeLogger","logger$2","newUUID","logger$1","logger","metadata: CacheMetadata","path","response: CacheServerResponse","EventEmitter","error: any","runEvent: RolloutRunEvent","handshakeEvent: RolloutHandshakeEvent","logger","child: ChildProcess","result: any","message: WorkerMessage","config","DEFAULT_WORKERS: Record<string, WorkerCommand>","logger","extractRolloutFunctions: any","buildFile: any","loadModule: any","selectRolloutFunction: any","error: any","paramsMetadata: Map<string, FunctionMetadata> | undefined","foundMetadata: FunctionMetadata | null","spawn","prefixPositions: number[]","lastValidJson: any","spansByPath: Record<string, any[]>","path","cachedSpan: CachedSpan","env: Record<string, string>","workerConfig: WorkerConfig","error: any","error","params: RolloutParam[]","sseClient: SSEClient | null","currentRunPromise: Promise<void> | null","sessionId","reloadTimeout: NodeJS.Timeout | null","Command","version"],"sources":["../package.json","../../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/package.json","../../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/lib/main.js","../../client/dist/index.mjs","../src/cache-server.ts","../src/sse-client.ts","../../types/dist/index.mjs","../src/utils.ts","../src/subprocess/executor.ts","../src/worker-registry.ts","../src/commands/dev/metadata.ts","../src/commands/dev/index.ts","../src/index.ts"],"sourcesContent":["","","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\n// Array of tips to display randomly\nconst TIPS = [\n '🔐 encrypt with Dotenvx: https://dotenvx.com',\n '🔐 prevent committing .env to code: https://dotenvx.com/precommit',\n '🔐 prevent building .env in docker: https://dotenvx.com/prebuild',\n '📡 add observability to secrets: https://dotenvx.com/ops',\n '👥 sync secrets across teammates & machines: https://dotenvx.com/ops',\n '🗂️ backup and recover secrets: https://dotenvx.com/ops',\n '✅ audit secrets and track compliance: https://dotenvx.com/ops',\n '🔄 add secrets lifecycle management: https://dotenvx.com/ops',\n '🔑 add access controls to secrets: https://dotenvx.com/ops',\n '🛠️ run anywhere with `dotenvx run -- yourcommand`',\n '⚙️ specify custom .env file path with { path: \\'/custom/path/.env\\' }',\n '⚙️ enable debug logging with { debug: true }',\n '⚙️ override existing env vars with { override: true }',\n '⚙️ suppress all logs with { quiet: true }',\n '⚙️ write to custom object with { processEnv: myObject }',\n '⚙️ load multiple .env files with { path: [\\'.env.local\\', \\'.env\\'] }'\n]\n\n// Get a random tip from the tips array\nfunction _getRandomTip () {\n return TIPS[Math.floor(Math.random() * TIPS.length)]\n}\n\nfunction parseBoolean (value) {\n if (typeof value === 'string') {\n return !['false', '0', 'no', 'off', ''].includes(value.toLowerCase())\n }\n return Boolean(value)\n}\n\nfunction supportsAnsi () {\n return process.stdout.isTTY // && process.env.TERM !== 'dumb'\n}\n\nfunction dim (text) {\n return supportsAnsi() ? `\\x1b[2m${text}\\x1b[0m` : text\n}\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n const obj = {}\n\n // Convert buffer to string\n let lines = src.toString()\n\n // Convert line breaks to same format\n lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n let match\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] || '')\n\n // Remove whitespace\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n obj[key] = value\n }\n\n return obj\n}\n\nfunction _parseVault (options) {\n options = options || {}\n\n const vaultPath = _vaultPath(options)\n options.path = vaultPath // parse .env.vault\n const result = DotenvModule.configDotenv(options)\n if (!result.parsed) {\n const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n err.code = 'MISSING_DATA'\n throw err\n }\n\n // handle scenario for comma separated keys - for use with key rotation\n // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n const keys = _dotenvKey(options).split(',')\n const length = keys.length\n\n let decrypted\n for (let i = 0; i < length; i++) {\n try {\n // Get full key\n const key = keys[i].trim()\n\n // Get instructions for decrypt\n const attrs = _instructions(result, key)\n\n // Decrypt\n decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n break\n } catch (error) {\n // last key\n if (i + 1 >= length) {\n throw error\n }\n // try next key\n }\n }\n\n // Parse decrypted .env string\n return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n console.error(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _log (message) {\n console.log(`[dotenv@${version}] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n // prioritize developer directly setting options.DOTENV_KEY\n if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n return options.DOTENV_KEY\n }\n\n // secondary infra already contains a DOTENV_KEY environment variable\n if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n return process.env.DOTENV_KEY\n }\n\n // fallback to empty string\n return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n // Parse DOTENV_KEY. Format is a URI\n let uri\n try {\n uri = new URL(dotenvKey)\n } catch (error) {\n if (error.code === 'ERR_INVALID_URL') {\n const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n throw error\n }\n\n // Get decrypt key\n const key = uri.password\n if (!key) {\n const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get environment\n const environment = uri.searchParams.get('environment')\n if (!environment) {\n const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n }\n\n // Get ciphertext payload\n const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n if (!ciphertext) {\n const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n throw err\n }\n\n return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n let possibleVaultPath = null\n\n if (options && options.path && options.path.length > 0) {\n if (Array.isArray(options.path)) {\n for (const filepath of options.path) {\n if (fs.existsSync(filepath)) {\n possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n }\n }\n } else {\n possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n }\n } else {\n possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n }\n\n if (fs.existsSync(possibleVaultPath)) {\n return possibleVaultPath\n }\n\n return null\n}\n\nfunction _resolveHome (envPath) {\n return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || (options && options.debug))\n const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (debug || !quiet) {\n _log('Loading env from encrypted .env.vault')\n }\n\n const parsed = DotenvModule._parseVault(options)\n\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n\n DotenvModule.populate(processEnv, parsed, options)\n\n return { parsed }\n}\n\nfunction configDotenv (options) {\n const dotenvPath = path.resolve(process.cwd(), '.env')\n let encoding = 'utf8'\n let processEnv = process.env\n if (options && options.processEnv != null) {\n processEnv = options.processEnv\n }\n let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || (options && options.debug))\n let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || (options && options.quiet))\n\n if (options && options.encoding) {\n encoding = options.encoding\n } else {\n if (debug) {\n _debug('No encoding is specified. UTF-8 is used by default')\n }\n }\n\n let optionPaths = [dotenvPath] // default, look for .env\n if (options && options.path) {\n if (!Array.isArray(options.path)) {\n optionPaths = [_resolveHome(options.path)]\n } else {\n optionPaths = [] // reset default\n for (const filepath of options.path) {\n optionPaths.push(_resolveHome(filepath))\n }\n }\n }\n\n // Build the parsed data in a temporary object (because we need to return it). Once we have the final\n // parsed data, we will combine it with process.env (or options.processEnv if provided).\n let lastError\n const parsedAll = {}\n for (const path of optionPaths) {\n try {\n // Specifying an encoding returns a string instead of a buffer\n const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n DotenvModule.populate(parsedAll, parsed, options)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${path} ${e.message}`)\n }\n lastError = e\n }\n }\n\n const populated = DotenvModule.populate(processEnv, parsedAll, options)\n\n // handle user settings DOTENV_CONFIG_ options inside .env file(s)\n debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug)\n quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet)\n\n if (debug || !quiet) {\n const keysCount = Object.keys(populated).length\n const shortPaths = []\n for (const filePath of optionPaths) {\n try {\n const relative = path.relative(process.cwd(), filePath)\n shortPaths.push(relative)\n } catch (e) {\n if (debug) {\n _debug(`Failed to load ${filePath} ${e.message}`)\n }\n lastError = e\n }\n }\n\n _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`-- tip: ${_getRandomTip()}`)}`)\n }\n\n if (lastError) {\n return { parsed: parsedAll, error: lastError }\n } else {\n return { parsed: parsedAll }\n }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n // fallback to original dotenv if DOTENV_KEY is not set\n if (_dotenvKey(options).length === 0) {\n return DotenvModule.configDotenv(options)\n }\n\n const vaultPath = _vaultPath(options)\n\n // dotenvKey exists but .env.vault file does not exist\n if (!vaultPath) {\n _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n return DotenvModule.configDotenv(options)\n }\n\n return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n const key = Buffer.from(keyStr.slice(-64), 'hex')\n let ciphertext = Buffer.from(encrypted, 'base64')\n\n const nonce = ciphertext.subarray(0, 12)\n const authTag = ciphertext.subarray(-16)\n ciphertext = ciphertext.subarray(12, -16)\n\n try {\n const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n aesgcm.setAuthTag(authTag)\n return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n } catch (error) {\n const isRange = error instanceof RangeError\n const invalidKeyLength = error.message === 'Invalid key length'\n const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n if (isRange || invalidKeyLength) {\n const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n err.code = 'INVALID_DOTENV_KEY'\n throw err\n } else if (decryptionFailed) {\n const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n err.code = 'DECRYPTION_FAILED'\n throw err\n } else {\n throw error\n }\n }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n const debug = Boolean(options && options.debug)\n const override = Boolean(options && options.override)\n const populated = {}\n\n if (typeof parsed !== 'object') {\n const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n err.code = 'OBJECT_REQUIRED'\n throw err\n }\n\n // Set process.env\n for (const key of Object.keys(parsed)) {\n if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n if (override === true) {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n\n if (debug) {\n if (override === true) {\n _debug(`\"${key}\" is already defined and WAS overwritten`)\n } else {\n _debug(`\"${key}\" is already defined and was NOT overwritten`)\n }\n }\n } else {\n processEnv[key] = parsed[key]\n populated[key] = parsed[key]\n }\n }\n\n return populated\n}\n\nconst DotenvModule = {\n configDotenv,\n _configVault,\n _parseVault,\n config,\n decrypt,\n parse,\n populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","import { config } from \"dotenv\";\nimport * as path from \"path\";\nimport pino from \"pino\";\nimport { PinoPretty } from \"pino-pretty\";\nimport { v4 } from \"uuid\";\n\n//#region package.json\nvar version = \"0.8.7\";\n\n//#endregion\n//#region src/version.ts\nfunction getLangVersion() {\n\tif (typeof process !== \"undefined\" && process.versions && process.versions.node) return `node-${process.versions.node}`;\n\tif (typeof navigator !== \"undefined\" && navigator.userAgent) return `browser-${navigator.userAgent}`;\n\treturn null;\n}\n\n//#endregion\n//#region src/resources/index.ts\nvar BaseResource = class {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tthis.baseHttpUrl = baseHttpUrl;\n\t\tthis.projectApiKey = projectApiKey;\n\t}\n\theaders() {\n\t\treturn {\n\t\t\tAuthorization: `Bearer ${this.projectApiKey}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\"\n\t\t};\n\t}\n\tasync handleError(response) {\n\t\tconst errorMsg = await response.text();\n\t\tthrow new Error(`${response.status} ${errorMsg}`);\n\t}\n};\n\n//#endregion\n//#region src/resources/browser-events.ts\nvar BrowserEventsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync send({ sessionId, traceId, events }) {\n\t\tconst payload = {\n\t\t\tsessionId,\n\t\t\ttraceId,\n\t\t\tevents,\n\t\t\tsource: getLangVersion() ?? \"javascript\",\n\t\t\tsdkVersion: version\n\t\t};\n\t\tconst jsonString = JSON.stringify(payload);\n\t\tconst compressedStream = new Blob([jsonString], { type: \"application/json\" }).stream().pipeThrough(new CompressionStream(\"gzip\"));\n\t\tconst compressedData = await new Response(compressedStream).arrayBuffer();\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/browser-sessions/events\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...this.headers(),\n\t\t\t\t\"Content-Encoding\": \"gzip\"\n\t\t\t},\n\t\t\tbody: compressedData\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/utils.ts\nfunction initializeLogger(options) {\n\tconst colorize = options?.colorize ?? true;\n\tconst level = options?.level ?? process.env.LMNR_LOG_LEVEL?.toLowerCase()?.trim() ?? \"info\";\n\treturn pino({ level }, PinoPretty({\n\t\tcolorize,\n\t\tminimumLevel: level\n\t}));\n}\nconst logger$2 = initializeLogger();\nconst isStringUUID = (id) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id);\nconst newUUID = () => {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n\telse return v4();\n};\nconst otelSpanIdToUUID = (spanId) => {\n\tlet id = spanId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 16) logger$2.warn(`Span ID ${spanId} is not 16 hex chars long. This is not a valid OpenTelemetry span ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$2.error(`Span ID ${spanId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.padStart(32, \"0\").replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst otelTraceIdToUUID = (traceId) => {\n\tlet id = traceId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 32) logger$2.warn(`Trace ID ${traceId} is not 32 hex chars long. This is not a valid OpenTelemetry trace ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$2.error(`Trace ID ${traceId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst slicePayload = (value, length) => {\n\tif (value === null || value === void 0) return value;\n\tconst str = JSON.stringify(value);\n\tif (str.length <= length) return value;\n\treturn str.slice(0, length) + \"...\";\n};\nconst loadEnv = (options) => {\n\tconst nodeEnv = process.env.NODE_ENV || \"development\";\n\tconst envDir = process.cwd();\n\tconst envFiles = [\n\t\t\".env\",\n\t\t\".env.local\",\n\t\t`.env.${nodeEnv}`,\n\t\t`.env.${nodeEnv}.local`\n\t];\n\tconst logLevel = process.env.LMNR_LOG_LEVEL ?? \"info\";\n\tconst verbose = [\"debug\", \"trace\"].includes(logLevel.trim().toLowerCase());\n\tconst quiet = options?.quiet ?? !verbose;\n\tconfig({\n\t\tpath: options?.paths ?? envFiles.map((envFile) => path.resolve(envDir, envFile)),\n\t\tquiet\n\t});\n};\n\n//#endregion\n//#region src/resources/datasets.ts\nconst logger$1 = initializeLogger();\nconst DEFAULT_DATASET_PULL_LIMIT = 100;\nconst DEFAULT_DATASET_PUSH_BATCH_SIZE = 100;\nvar DatasetsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* List all datasets.\n\t*\n\t* @returns {Promise<Dataset[]>} Array of datasets\n\t*/\n\tasync listDatasets() {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/datasets\", {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Get a dataset by name.\n\t*\n\t* @param {string} name - Name of the dataset\n\t* @returns {Promise<Dataset[]>} Array of datasets with matching name\n\t*/\n\tasync getDatasetByName(name) {\n\t\tconst params = new URLSearchParams({ name });\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Push datapoints to a dataset.\n\t*\n\t* @param {Object} options - Push options\n\t* @param {Datapoint<D, T>[]} options.points - Datapoints to push\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.batchSize] - Batch size for pushing (default: 100)\n\t* @param {boolean} [options.createDataset] - Whether to create the dataset if it doesn't exist\n\t* @returns {Promise<PushDatapointsResponse | undefined>}\n\t*/\n\tasync push({ points, name, id, batchSize = DEFAULT_DATASET_PUSH_BATCH_SIZE, createDataset = false }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tif (createDataset && !name) throw new Error(\"Name must be provided when creating a new dataset\");\n\t\tconst identifier = name ? { name } : { datasetId: id };\n\t\tconst totalBatches = Math.ceil(points.length / batchSize);\n\t\tlet response;\n\t\tfor (let i = 0; i < points.length; i += batchSize) {\n\t\t\tconst batchNum = Math.floor(i / batchSize) + 1;\n\t\t\tlogger$1.debug(`Pushing batch ${batchNum} of ${totalBatches}`);\n\t\t\tconst batch = points.slice(i, i + batchSize);\n\t\t\tconst fetchResponse = await fetch(this.baseHttpUrl + \"/v1/datasets/datapoints\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t...identifier,\n\t\t\t\t\tdatapoints: batch.map((point) => ({\n\t\t\t\t\t\tdata: point.data,\n\t\t\t\t\t\ttarget: point.target ?? {},\n\t\t\t\t\t\tmetadata: point.metadata ?? {}\n\t\t\t\t\t})),\n\t\t\t\t\tcreateDataset\n\t\t\t\t})\n\t\t\t});\n\t\t\tif (fetchResponse.status !== 200 && fetchResponse.status !== 201) await this.handleError(fetchResponse);\n\t\t\tresponse = await fetchResponse.json();\n\t\t}\n\t\treturn response;\n\t}\n\t/**\n\t* Pull datapoints from a dataset.\n\t*\n\t* @param {Object} options - Pull options\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.limit] - Maximum number of datapoints to return (default: 100)\n\t* @param {number} [options.offset] - Offset for pagination (default: 0)\n\t* @returns {Promise<GetDatapointsResponse<D, T>>}\n\t*/\n\tasync pull({ name, id, limit = DEFAULT_DATASET_PULL_LIMIT, offset = 0 }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tconst paramsObj = {\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t};\n\t\tif (name) paramsObj.name = name;\n\t\telse paramsObj.datasetId = id;\n\t\tconst params = new URLSearchParams(paramsObj);\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n\n//#endregion\n//#region src/resources/evals.ts\nconst logger = initializeLogger();\nconst INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH = 16e6;\nvar EvalsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Initialize an evaluation.\n\t*\n\t* @param {string} name - Name of the evaluation\n\t* @param {string} groupName - Group name of the evaluation\n\t* @param {Record<string, any>} metadata - Optional metadata\n\t* @returns {Promise<InitEvaluationResponse>} Response from the evaluation initialization\n\t*/\n\tasync init(name, groupName, metadata) {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evals\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname: name ?? null,\n\t\t\t\tgroupName: groupName ?? null,\n\t\t\t\tmetadata: metadata ?? null\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t*\n\t* @param {string} [name] - Optional name of the evaluation\n\t* @param {string} [groupName] - An identifier to group evaluations\n\t* @param {Record<string, any>} [metadata] - Optional metadata\n\t* @returns {Promise<StringUUID>} The evaluation ID\n\t*/\n\tasync create(args) {\n\t\treturn (await this.init(args?.name, args?.groupName, args?.metadata)).id;\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t* @deprecated use `create` instead.\n\t*/\n\tasync createEvaluation(name, groupName, metadata) {\n\t\treturn (await this.init(name, groupName, metadata)).id;\n\t}\n\t/**\n\t* Create a datapoint for an evaluation.\n\t*\n\t* @param {Object} options - Create datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {D} options.data - The input data for the executor\n\t* @param {T} [options.target] - The target/expected output for evaluators\n\t* @param {Record<string, any>} [options.metadata] - Optional metadata\n\t* @param {number} [options.index] - Optional index of the datapoint\n\t* @param {string} [options.traceId] - Optional trace ID\n\t* @returns {Promise<StringUUID>} The datapoint ID\n\t*/\n\tasync createDatapoint({ evalId, data, target, metadata, index, traceId }) {\n\t\tconst datapointId = newUUID();\n\t\tconst partialDatapoint = {\n\t\t\tid: datapointId,\n\t\t\tdata,\n\t\t\ttarget,\n\t\t\tindex: index ?? 0,\n\t\t\ttraceId: traceId ?? newUUID(),\n\t\t\texecutorSpanId: newUUID(),\n\t\t\tmetadata\n\t\t};\n\t\tawait this.saveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints: [partialDatapoint]\n\t\t});\n\t\treturn datapointId;\n\t}\n\t/**\n\t* Update a datapoint with evaluation results.\n\t*\n\t* @param {Object} options - Update datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {string} options.datapointId - The datapoint ID\n\t* @param {Record<string, number>} options.scores - The scores\n\t* @param {O} [options.executorOutput] - The executor output\n\t* @returns {Promise<void>}\n\t*/\n\tasync updateDatapoint({ evalId, datapointId, scores, executorOutput }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints/${datapointId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\texecutorOutput,\n\t\t\t\tscores\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Save evaluation datapoints.\n\t*\n\t* @param {Object} options - Save datapoints options\n\t* @param {string} options.evalId - ID of the evaluation\n\t* @param {EvaluationDatapoint<D, T, O>[]} options.datapoints - Datapoint to add\n\t* @param {string} [options.groupName] - Group name of the evaluation\n\t* @returns {Promise<void>} Response from the datapoint addition\n\t*/\n\tasync saveDatapoints({ evalId, datapoints, groupName }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t...d,\n\t\t\t\t\tdata: slicePayload(d.data, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\ttarget: slicePayload(d.target, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH)\n\t\t\t\t})),\n\t\t\t\tgroupName: groupName ?? null\n\t\t\t})\n\t\t});\n\t\tif (response.status === 413) return await this.retrySaveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints,\n\t\t\tgroupName\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Get evaluation datapoints.\n\t*\n\t* @deprecated Use `client.datasets.pull()` instead.\n\t* @param {Object} options - Get datapoints options\n\t* @param {string} options.datasetName - Name of the dataset\n\t* @param {number} options.offset - Offset at which to start the query\n\t* @param {number} options.limit - Maximum number of datapoints to return\n\t* @returns {Promise<GetDatapointsResponse>} Response from the datapoint retrieval\n\t*/\n\tasync getDatapoints({ datasetName, offset, limit }) {\n\t\tlogger.warn(\"evals.getDatapoints() is deprecated. Use client.datasets.pull() instead.\");\n\t\tconst params = new URLSearchParams({\n\t\t\tname: datasetName,\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t});\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn await response.json();\n\t}\n\tasync retrySaveDatapoints({ evalId, datapoints, groupName, maxRetries = 25, initialLength = INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH }) {\n\t\tlet length = initialLength;\n\t\tlet lastResponse = null;\n\t\tfor (let i = 0; i < maxRetries; i++) {\n\t\t\tlogger.debug(`Retrying save datapoints... ${i + 1} of ${maxRetries}, length: ${length}`);\n\t\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t\t...d,\n\t\t\t\t\t\tdata: slicePayload(d.data, length),\n\t\t\t\t\t\ttarget: slicePayload(d.target, length),\n\t\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, length)\n\t\t\t\t\t})),\n\t\t\t\t\tgroupName: groupName ?? null\n\t\t\t\t})\n\t\t\t});\n\t\t\tlastResponse = response;\n\t\t\tlength = Math.floor(length / 2);\n\t\t\tif (response.status !== 413) break;\n\t\t}\n\t\tif (lastResponse && !lastResponse.ok) await this.handleError(lastResponse);\n\t}\n};\n\n//#endregion\n//#region src/resources/evaluators.ts\nvar EvaluatorScoreSourceType = /* @__PURE__ */ function(EvaluatorScoreSourceType$1) {\n\tEvaluatorScoreSourceType$1[\"Evaluator\"] = \"Evaluator\";\n\tEvaluatorScoreSourceType$1[\"Code\"] = \"Code\";\n\treturn EvaluatorScoreSourceType$1;\n}(EvaluatorScoreSourceType || {});\n/**\n* Resource for creating evaluator scores\n*/\nvar EvaluatorsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Create a score for a span or trace\n\t*\n\t* @param {ScoreOptions} options - Score creation options\n\t* @param {string} options.name - Name of the score\n\t* @param {string} [options.traceId] - The trace ID to score (will be attached to top-level span)\n\t* @param {string} [options.spanId] - The span ID to score\n\t* @param {Record<string, any>} [options.metadata] - Additional metadata\n\t* @param {number} options.score - The score value (float)\n\t* @returns {Promise<void>}\n\t*\n\t* @example\n\t* // Score by trace ID (will attach to root span)\n\t* await evaluators.score({\n\t* name: \"quality\",\n\t* traceId: \"trace-id-here\",\n\t* score: 0.95,\n\t* metadata: { model: \"gpt-4\" }\n\t* });\n\t*\n\t* @example\n\t* // Score by span ID\n\t* await evaluators.score({\n\t* name: \"relevance\",\n\t* spanId: \"span-id-here\",\n\t* score: 0.87\n\t* });\n\t*/\n\tasync score(options) {\n\t\tconst { name, metadata, score } = options;\n\t\tlet payload;\n\t\tif (\"traceId\" in options && options.traceId) {\n\t\t\tconst formattedTraceId = isStringUUID(options.traceId) ? options.traceId : otelTraceIdToUUID(options.traceId);\n\t\t\tpayload = {\n\t\t\t\tname,\n\t\t\t\tmetadata,\n\t\t\t\tscore,\n\t\t\t\tsource: EvaluatorScoreSourceType.Code,\n\t\t\t\ttraceId: formattedTraceId\n\t\t\t};\n\t\t} else if (\"spanId\" in options && options.spanId) {\n\t\t\tconst formattedSpanId = isStringUUID(options.spanId) ? options.spanId : otelSpanIdToUUID(options.spanId);\n\t\t\tpayload = {\n\t\t\t\tname,\n\t\t\t\tmetadata,\n\t\t\t\tscore,\n\t\t\t\tsource: EvaluatorScoreSourceType.Code,\n\t\t\t\tspanId: formattedSpanId\n\t\t\t};\n\t\t} else throw new Error(\"Either 'traceId' or 'spanId' must be provided.\");\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evaluators/score\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/resources/rollout-sessions.ts\nvar RolloutSessionsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Connects to the SSE stream for rollout debugging sessions\n\t* Returns the Response object for streaming SSE events\n\t*/\n\tasync connect({ sessionId, name, params, signal }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...this.headers(),\n\t\t\t\t\"Accept\": \"text/event-stream\"\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname,\n\t\t\t\tparams\n\t\t\t}),\n\t\t\tsignal\n\t\t});\n\t\tif (!response.ok) throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);\n\t\tif (!response.body) throw new Error(\"No response body\");\n\t\treturn response;\n\t}\n\tasync delete({ sessionId }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\tasync setStatus({ sessionId, status }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/status`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({ status })\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\tasync sendSpanUpdate({ sessionId, span }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/update`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttype: \"spanStart\",\n\t\t\t\tspanId: otelSpanIdToUUID(span.spanId),\n\t\t\t\ttraceId: otelTraceIdToUUID(span.traceId),\n\t\t\t\tparentSpanId: span.parentSpanId ? otelSpanIdToUUID(span.parentSpanId) : void 0,\n\t\t\t\tattributes: span.attributes,\n\t\t\t\tstartTime: span.startTime,\n\t\t\t\tname: span.name,\n\t\t\t\tspanType: span.spanType\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n\n//#endregion\n//#region src/resources/sql.ts\nvar SqlResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync query(sql, parameters = {}) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/sql/query`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { ...this.headers() },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tquery: sql,\n\t\t\t\tparameters\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn (await response.json()).data;\n\t}\n};\n\n//#endregion\n//#region src/resources/tags.ts\n/** Resource for tagging traces. */\nvar TagsResource = class extends BaseResource {\n\t/** Resource for tagging traces. */\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Tag a trace with a list of tags. Note that the trace must be ended before\n\t* tagging it. You may want to call `await Laminar.flush()` after the trace\n\t* that you want to tag.\n\t*\n\t* @param {string | StringUUID} trace_id - The trace id to tag.\n\t* @param {string[] | string} tags - The tag or list of tags to add to the trace.\n\t* @returns {Promise<any>} The response from the server.\n\t* @example\n\t* ```javascript\n\t* import { Laminar, observe, LaminarClient } from \"@lmnr-ai/lmnr\";\n\t* Laminar.initialize();\n\t* const client = new LaminarClient();\n\t* let traceId: StringUUID | null = null;\n\t* // Make sure this is called outside of traced context.\n\t* await observe(\n\t* {\n\t* name: \"my-trace\",\n\t* },\n\t* async () => {\n\t* traceId = await Laminar.getTraceId();\n\t* await foo();\n\t* },\n\t* );\n\t*\n\t* // or make sure the trace is ended by this point.\n\t* await Laminar.flush();\n\t* if (traceId) {\n\t* await client.tags.tag(traceId, [\"tag1\", \"tag2\"]);\n\t* }\n\t* ```\n\t*/\n\tasync tag(trace_id, tags) {\n\t\tconst traceTags = Array.isArray(tags) ? tags : [tags];\n\t\tconst formattedTraceId = isStringUUID(trace_id) ? trace_id : otelTraceIdToUUID(trace_id);\n\t\tconst url = this.baseHttpUrl + \"/v1/tag\";\n\t\tconst payload = {\n\t\t\t\"traceId\": formattedTraceId,\n\t\t\t\"names\": traceTags\n\t\t};\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n\n//#endregion\n//#region src/index.ts\nvar LaminarClient = class {\n\tconstructor({ baseUrl, projectApiKey, port } = {}) {\n\t\tloadEnv();\n\t\tthis.projectApiKey = projectApiKey ?? process.env.LMNR_PROJECT_API_KEY;\n\t\tconst httpPort = port ?? (baseUrl?.match(/:\\d{1,5}$/g) ? parseInt(baseUrl.match(/:\\d{1,5}$/g)[0].slice(1)) : 443);\n\t\tthis.baseUrl = `${(baseUrl ?? process.env.LMNR_BASE_URL)?.replace(/\\/$/, \"\").replace(/:\\d{1,5}$/g, \"\") ?? \"https://api.lmnr.ai\"}:${httpPort}`;\n\t\tthis._browserEvents = new BrowserEventsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._datasets = new DatasetsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evals = new EvalsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evaluators = new EvaluatorsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._rolloutSessions = new RolloutSessionsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._sql = new SqlResource(this.baseUrl, this.projectApiKey);\n\t\tthis._tags = new TagsResource(this.baseUrl, this.projectApiKey);\n\t}\n\tget browserEvents() {\n\t\treturn this._browserEvents;\n\t}\n\tget datasets() {\n\t\treturn this._datasets;\n\t}\n\tget evals() {\n\t\treturn this._evals;\n\t}\n\tget evaluators() {\n\t\treturn this._evaluators;\n\t}\n\tget rolloutSessions() {\n\t\treturn this._rolloutSessions;\n\t}\n\tget sql() {\n\t\treturn this._sql;\n\t}\n\tget tags() {\n\t\treturn this._tags;\n\t}\n};\n\n//#endregion\nexport { LaminarClient };\n//# sourceMappingURL=index.mjs.map","import {\n CachedSpan,\n CacheMetadata,\n CacheServerResponse,\n} from '@lmnr-ai/types';\nimport * as http from 'http';\n\ninterface CacheServerResult {\n port: number;\n server: http.Server;\n cache: Map<string, CachedSpan>;\n setMetadata: (metadata: CacheMetadata) => void;\n}\n\nconst DEFAULT_START_PORT = 35667;\n\n/**\n * Finds an available port starting from the given port number\n */\nasync function findAvailablePort(startPort: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = http.createServer();\n\n server.listen(startPort, () => {\n const port = (server.address() as any).port;\n server.close(() => resolve(port));\n });\n\n server.on('error', (err: any) => {\n if (err.code === 'EADDRINUSE') {\n // Port is in use, try the next one\n resolve(findAvailablePort(startPort + 1));\n } else {\n reject(err as Error);\n }\n });\n });\n}\n\n/**\n * Parses request body as JSON\n */\nfunction parseBody(req: http.IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch (err) {\n reject(new Error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`));\n }\n });\n\n req.on('error', reject);\n });\n}\n\n/**\n * Starts a local cache server for storing and retrieving cached LLM responses\n * during rollout debugging sessions.\n *\n * @param startPort - Optional starting port number (defaults to 35667)\n * @returns Server information including port, server instance, cache, and metadata setter\n */\nexport async function startCacheServer(\n startPort: number = DEFAULT_START_PORT,\n): Promise<CacheServerResult> {\n const cache = new Map<string, CachedSpan>();\n let metadata: CacheMetadata = {\n pathToCount: {},\n overrides: undefined,\n };\n\n const server = http.createServer((req, res) => {\n (async () => {\n // Set CORS headers for local development\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n // Handle preflight requests\n if (req.method === 'OPTIONS') {\n res.writeHead(200);\n res.end();\n return;\n }\n\n // Health check endpoint\n if (req.method === 'GET' && req.url === '/health') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ status: 'ok' }));\n return;\n }\n\n // Cached response endpoint\n if (req.method === 'POST' && req.url === '/cached') {\n try {\n const body = await parseBody(req);\n const { path, index } = body;\n\n if (typeof path !== 'string' || typeof index !== 'number') {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(\n { error: 'Invalid request: path (string) and index (number) required' },\n ));\n return;\n }\n\n // Cache key is ${index}:${path} to handle colons in paths\n const cacheKey = `${index}:${path}`;\n const cachedSpan = cache.get(cacheKey);\n\n // Return cached span with metadata\n const response: CacheServerResponse = {\n span: cachedSpan,\n pathToCount: metadata.pathToCount,\n overrides: metadata.overrides,\n };\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(response));\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(\n { error: err instanceof Error ? err.message : String(err) },\n ));\n }\n return;\n }\n\n // 404 for unknown routes\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n })().catch((error) => {\n // Catch any unexpected errors and send 500 response\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({\n error: error instanceof Error ? error.message : 'Internal server error',\n }));\n }\n });\n });\n\n const port = await findAvailablePort(startPort);\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n resolve({\n port,\n server,\n cache,\n setMetadata: (newMetadata: CacheMetadata) => {\n metadata = newMetadata;\n },\n });\n });\n\n server.on('error', reject);\n });\n}\n","import { LaminarClient } from '@lmnr-ai/client';\nimport { RolloutHandshakeEvent, RolloutParam, RolloutRunEvent } from '@lmnr-ai/types';\nimport { EventEmitter } from 'events';\nimport { createParser } from 'eventsource-parser';\n\nconst HEARTBEAT_INTERVAL = 5000; // 5 seconds\nconst MAX_MISSED_HEARTBEATS = 3; // N missed intervals before reconnect\n\nexport interface SSEClientOptions {\n client: LaminarClient;\n sessionId: string;\n params: RolloutParam[];\n name: string;\n}\n\n/**\n * SSE client for rollout debugging sessions\n * Connects to the Laminar backend and listens for run events\n */\nexport class SSEClient extends EventEmitter {\n private client: LaminarClient;\n private sessionId: string;\n private params: RolloutParam[];\n private name: string;\n private abortController?: AbortController;\n private reconnectTimer?: NodeJS.Timeout;\n private lastHeartbeat: number = Date.now();\n private heartbeatCheckTimer?: NodeJS.Timeout;\n private isShutdown: boolean = false;\n\n constructor(options: SSEClientOptions) {\n super();\n this.client = options.client;\n this.sessionId = options.sessionId;\n this.params = options.params;\n this.name = options.name;\n }\n\n /**\n * Connects to the SSE endpoint\n */\n async connectAndListen(): Promise<void> {\n if (this.isShutdown) {\n return;\n }\n\n this.abortController = new AbortController();\n this.lastHeartbeat = Date.now();\n\n try {\n const response = await this.client.rolloutSessions.connect({\n sessionId: this.sessionId,\n params: this.params,\n signal: this.abortController.signal,\n name: this.name,\n });\n\n this.emit('connected');\n this.startHeartbeatCheck();\n\n // Parse SSE stream\n await this.parseSSEStream(response.body!);\n } catch (error: any) {\n if (error.name === 'AbortError') {\n // Connection was aborted intentionally\n return;\n }\n\n this.emit('error', error);\n\n if (!this.isShutdown) {\n // Attempt to reconnect\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Parses SSE stream and emits events\n */\n private async parseSSEStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n\n // Create SSE parser with proper event handling\n const parser = createParser({\n onEvent: (event: any) => {\n this.processSSEEvent(event);\n },\n });\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n // Feed the chunks to the parser\n const chunk = decoder.decode(value, { stream: true });\n parser.feed(chunk);\n }\n } finally {\n reader.releaseLock();\n }\n\n // Connection ended, try to reconnect if not shutdown\n if (!this.isShutdown) {\n this.scheduleReconnect();\n }\n }\n\n /**\n * Processes a parsed SSE event\n */\n private processSSEEvent(event: any): void {\n if (!event.data) {\n return;\n }\n\n try {\n // The event.event field contains the event type ('heartbeat' or 'run')\n // The event.data field contains the JSON payload\n if (event.event === 'heartbeat') {\n this.lastHeartbeat = Date.now();\n this.emit('heartbeat');\n } else if (event.event === 'run') {\n const parsedData = JSON.parse(event.data);\n const runEvent: RolloutRunEvent = {\n event_type: 'run',\n data: parsedData,\n };\n this.emit('run', runEvent);\n } else if (event.event === 'handshake') {\n const parsedData = JSON.parse(event.data);\n const handshakeEvent: RolloutHandshakeEvent = {\n event_type: 'handshake',\n data: parsedData,\n };\n this.emit('handshake', handshakeEvent);\n } else if (event.event === 'stop') {\n this.emit('stop');\n }\n } catch (error: any) {\n this.emit('error', new Error(`Failed to parse SSE event data: ${error}`));\n }\n }\n\n /**\n * Starts checking for missed heartbeats\n */\n private startHeartbeatCheck(): void {\n this.stopHeartbeatCheck();\n\n this.heartbeatCheckTimer = setInterval(() => {\n const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeat;\n const maxAllowedTime = HEARTBEAT_INTERVAL * MAX_MISSED_HEARTBEATS;\n\n if (timeSinceLastHeartbeat > maxAllowedTime) {\n this.emit('heartbeat_timeout');\n this.reconnect();\n }\n }, HEARTBEAT_INTERVAL);\n }\n\n /**\n * Stops heartbeat checking\n */\n private stopHeartbeatCheck(): void {\n if (this.heartbeatCheckTimer) {\n clearInterval(this.heartbeatCheckTimer);\n this.heartbeatCheckTimer = undefined;\n }\n }\n\n /**\n * Schedules a reconnection attempt\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer || this.isShutdown) {\n return;\n }\n\n this.emit('reconnecting');\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n this.reconnect();\n }, 1000); // Wait 1 second before reconnecting\n }\n\n /**\n * Reconnects to the SSE endpoint\n */\n private reconnect(): void {\n this.disconnect(true);\n this.connectAndListen().catch(error => {\n this.emit('error', error);\n });\n }\n\n /**\n * Disconnects from the SSE endpoint\n */\n private disconnect(stopReconnect: boolean = true): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = undefined;\n }\n\n this.stopHeartbeatCheck();\n\n if (stopReconnect && this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n }\n\n /**\n * Updates the function metadata (params, name) and reconnects\n */\n updateMetadata(params: RolloutParam[], name: string): void {\n this.params = params;\n this.name = name;\n\n // Reconnect to send updated metadata\n this.reconnect();\n }\n\n /**\n * Shuts down the SSE client gracefully\n */\n shutdown(): void {\n this.isShutdown = true;\n this.disconnect(true);\n this.emit('shutdown');\n this.removeAllListeners();\n }\n}\n\n/**\n * Creates an SSE client (does not auto-connect)\n * Call client.connect() after registering event listeners\n */\nexport function createSSEClient(options: SSEClientOptions): SSEClient {\n return new SSEClient(options);\n}\n","//#region src/tracing.ts\n/**\n* Tracing levels to conditionally disable tracing.\n*\n* OFF - No tracing is sent.\n* META_ONLY - Only metadata is sent (e.g. tokens, costs, etc.).\n* ALL - All data is sent.\n*/\nlet TracingLevel = /* @__PURE__ */ function(TracingLevel$1) {\n\tTracingLevel$1[\"OFF\"] = \"off\";\n\tTracingLevel$1[\"META_ONLY\"] = \"meta_only\";\n\tTracingLevel$1[\"ALL\"] = \"all\";\n\treturn TracingLevel$1;\n}({});\n\n//#endregion\n//#region src/worker-protocol.ts\n/**\n* Message prefix for protocol messages in stdout\n*/\nconst WORKER_MESSAGE_PREFIX = \"__LMNR_WORKER__:\";\n\n//#endregion\nexport { TracingLevel, WORKER_MESSAGE_PREFIX };\n//# sourceMappingURL=index.mjs.map","import pino, { Level } from 'pino';\nimport { PinoPretty } from 'pino-pretty';\n\nexport function initializeLogger(options?: { colorize?: boolean; level?: Level }) {\n const colorize = options?.colorize ?? true;\n const level =\n options?.level ??\n (process.env.LMNR_LOG_LEVEL?.toLowerCase()?.trim() as Level) ??\n 'info';\n\n return pino(\n {\n level,\n },\n PinoPretty({\n colorize,\n minimumLevel: level,\n }),\n );\n}\n","import { WORKER_MESSAGE_PREFIX, WorkerConfig, WorkerMessage } from '@lmnr-ai/types';\nimport { ChildProcess, spawn } from 'child_process';\nimport * as readline from 'readline';\n\nimport { initializeLogger } from '../utils';\n\nconst logger = initializeLogger();\n\nexport interface ExecuteOptions {\n command: string;\n args: string[];\n config: WorkerConfig;\n}\n\n/**\n * Track and kill the currently running subprocess\n */\nexport class SubprocessManager {\n private currentProcess: ChildProcess | null = null;\n\n /**\n * Execute a subprocess and track it\n */\n async execute(options: ExecuteOptions): Promise<any> {\n const { command, args, config } = options;\n\n // Spawn the worker process\n const child: ChildProcess = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n this.currentProcess = child;\n\n return new Promise((resolve, reject) => {\n let result: any = undefined;\n let hasError = false;\n\n // Set up readline interface for stdout\n const rl = readline.createInterface({\n input: child.stdout!,\n crlfDelay: Infinity,\n });\n\n // Handle messages from worker\n rl.on('line', (line: string) => {\n // Check if this is a worker protocol message or user output\n if (line.startsWith(WORKER_MESSAGE_PREFIX)) {\n // Parse worker protocol message\n try {\n const messageJson = line.substring(WORKER_MESSAGE_PREFIX.length);\n const message: WorkerMessage = JSON.parse(messageJson);\n\n switch (message.type) {\n // wrapped in a block for const not to be hoisted\n case 'log': {\n // Forward log messages through pino logger\n logger[message.level](message.message);\n break;\n }\n case 'result':\n result = message.data;\n break;\n\n case 'error':\n hasError = true;\n logger.error(`Worker error: ${message.error}`);\n if (message.stack) {\n logger.error(message.stack);\n }\n break;\n }\n } catch {\n logger.error(`Failed to parse worker protocol message: ${line}`);\n }\n } else {\n // This is user output from console.log - pass it through transparently\n console.log(line);\n }\n });\n\n // Pass through stderr for user's console.error\n child.stderr!.on('data', (data: Buffer) => {\n process.stderr.write(data);\n });\n\n // Handle process exit\n child.on('exit', (code: number | null, signal: string | null) => {\n if (this.currentProcess?.pid === child.pid) {\n this.currentProcess = null;\n }\n\n if (signal) {\n reject(new Error(`Worker terminated by signal: ${signal}`));\n } else if (code === 0) {\n resolve(result);\n } else {\n if (!hasError) {\n logger.error(`Worker exited with code ${code}`);\n }\n reject(new Error(`Worker exited with code ${code}`));\n }\n });\n\n // Handle spawn errors\n child.on('error', (error: Error) => {\n this.currentProcess = null;\n reject(new Error(`Failed to spawn worker: ${error.message}`));\n });\n\n // Send configuration to worker via stdin\n child.stdin?.write(JSON.stringify(config) + '\\n');\n child.stdin?.end();\n });\n }\n\n /**\n * Kill the currently running subprocess\n * @returns true if a process was killed, false if no process was running\n */\n kill(): boolean {\n if (this.currentProcess) {\n const processToKill = this.currentProcess;\n this.currentProcess.kill('SIGTERM');\n\n // Fallback to SIGKILL after 5 seconds\n setTimeout(() => {\n // exitCode is null if the process is still running\n if (processToKill && processToKill.exitCode === null) {\n logger.warn('Child process did not terminate, using SIGKILL');\n processToKill.kill('SIGKILL');\n }\n }, 5000);\n return true;\n }\n return false;\n }\n\n /**\n * Check if a subprocess is currently running\n */\n isRunning(): boolean {\n return this.currentProcess !== null;\n }\n}\n","import * as path from 'path';\n\nexport interface WorkerCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Default workers mapped by file extension\n */\nconst DEFAULT_WORKERS: Record<string, WorkerCommand> = {\n '.ts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.cts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.mts': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.tsx': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.jsx': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.js': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.mjs': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.cjs': {\n command: 'node',\n args: [], // Will be resolved dynamically\n },\n '.py': {\n command: 'python3',\n args: ['-m', 'lmnr.cli.worker'],\n },\n};\n\n/**\n * Get the worker command for a given file path or module.\n * Resolves the TypeScript worker dynamically from @lmnr-ai/lmnr package.\n */\nexport function getWorkerCommand(\n filePath?: string,\n options?: { pythonModule?: string },\n): WorkerCommand {\n // If Python module mode, always use Python worker\n if (options?.pythonModule) {\n return {\n command: 'python3',\n args: ['-m', 'lmnr.cli.worker'],\n };\n }\n\n // Otherwise determine by file extension\n if (!filePath) {\n throw new Error('Either filePath or pythonModule must be provided');\n }\n\n const ext = path.extname(filePath);\n\n if (!DEFAULT_WORKERS[ext]) {\n throw new Error(\n `Unsupported file extension: ${ext}. ` +\n `Supported extensions: ${Object.keys(DEFAULT_WORKERS).join(', ')}`,\n );\n }\n\n const worker = DEFAULT_WORKERS[ext];\n\n // For TypeScript/JavaScript files, resolve the worker from @lmnr-ai/lmnr\n if (['.ts', '.tsx', '.js', '.mjs', '.cjs', '.mts', '.cts', '.jsx'].includes(ext)) {\n try {\n // Try to resolve the worker from @lmnr-ai/lmnr package\n const workerPath = require.resolve('@lmnr-ai/lmnr/dist/cli/worker/index.cjs');\n return {\n command: worker.command,\n args: [workerPath],\n };\n } catch (error) {\n throw new Error(\n 'Failed to resolve TypeScript/JavaScript worker from @lmnr-ai/lmnr package. ' +\n 'Make sure @lmnr-ai/lmnr is installed. ' +\n `Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return worker;\n}\n\n/**\n * Get a custom worker command with overrides.\n * Allows users to specify custom commands via CLI flags.\n */\nexport function getCustomWorkerCommand(\n command: string,\n args: string[],\n): WorkerCommand {\n return { command, args };\n}\n","import type { RolloutParam } from '@lmnr-ai/types';\nimport * as path from 'path';\n\nimport { initializeLogger } from '../../utils';\n\nconst logger = initializeLogger();\n\nexport interface FunctionMetadata {\n name: string; // The span name from observe({ name: '...' })\n exportName: string; // The actual export/variable name\n params: RolloutParam[];\n}\n\nexport interface DiscoveredMetadata {\n functionName: string;\n params: RolloutParam[];\n}\n\n// Extensions that use TypeScript/JavaScript build and runtime discovery\nconst TS_JS_EXTENSIONS = [\n '.ts',\n '.tsx',\n '.js',\n '.mjs',\n '.cjs',\n '.jsx',\n '.mts',\n '.cts',\n];\n\n// All extensions that support metadata discovery\nexport const EXTENSIONS_TO_DISCOVER_METADATA = [...TS_JS_EXTENSIONS, '.py'];\n\n/**\n * Protocol prefix for metadata discovery responses\n * This allows us to safely parse JSON even if there are other log statements in stdout\n */\nexport const METADATA_PROTOCOL_PREFIX = 'LMNR_METADATA:';\n\nconst logLmnrPackageNotFoundAndExit = () => {\n logger.error(\n '@lmnr-ai/lmnr package not found or outdated. ' +\n 'For JS/TS projects, please install the latest version of @lmnr-ai/lmnr in your project: ' +\n 'npm install @lmnr-ai/lmnr\\n' +\n 'You might need to run `lmnr-cli` from the root of your project',\n );\n process.exit(1);\n};\n\n/**\n * Discovers function metadata for TypeScript and JavaScript files by:\n * 1. Extracting TypeScript metadata (params with types from source - TS only)\n * 2. Building and loading the module with esbuild\n * 3. Selecting the appropriate function\n * 4. Matching metadata by span name\n *\n * For JavaScript files, TypeScript metadata extraction fails gracefully, but runtime\n * parameter extraction via regex still works (param names without types).\n */\nconst discoverTypeScriptMetadata = async (\n filePath: string,\n options: { function?: string; externalPackages?: string[]; dynamicImportsToSkip?: string[] },\n): Promise<DiscoveredMetadata> => {\n let extractRolloutFunctions: any;\n let buildFile: any;\n let loadModule: any;\n let selectRolloutFunction: any;\n\n try {\n /* eslint-disable @typescript-eslint/no-require-imports */\n // Use dynamic require to prevent bundler from trying to resolve at build time\n const lmnrPackage = '@lmnr-ai/lmnr';\n const tsParserPath = require.resolve(`${lmnrPackage}/dist/cli/worker/ts-parser.cjs`);\n const buildModulePath = require.resolve(`${lmnrPackage}/dist/cli/worker/build.cjs`);\n\n // Clear require cache to ensure we get fresh modules on reload\n delete require.cache[tsParserPath];\n delete require.cache[buildModulePath];\n\n extractRolloutFunctions = require(tsParserPath).extractRolloutFunctions;\n const buildModule = require(buildModulePath);\n buildFile = buildModule.buildFile;\n loadModule = buildModule.loadModule;\n selectRolloutFunction = buildModule.selectRolloutFunction;\n /* eslint-enable @typescript-eslint/no-require-imports */\n\n if (!extractRolloutFunctions || !buildFile || !loadModule || !selectRolloutFunction) {\n logger.error(\n \"Missing exports from @lmnr-ai/lmnr modules. \" +\n \"This may indicate an outdated package version.\",\n );\n logLmnrPackageNotFoundAndExit();\n }\n } catch (error: any) {\n if (error.code === 'MODULE_NOT_FOUND') {\n logLmnrPackageNotFoundAndExit();\n }\n // Re-throw any other errors (syntax errors, etc.)\n logger.error(`Unexpected error loading @lmnr-ai/lmnr modules: ${error.message}`);\n throw error;\n }\n\n\n // Extract TypeScript metadata\n let paramsMetadata: Map<string, FunctionMetadata> | undefined;\n try {\n paramsMetadata = extractRolloutFunctions(filePath);\n logger.debug(`Extracted TypeScript metadata for ${paramsMetadata?.size} functions`);\n } catch (error) {\n logger.warn(\n 'Failed to extract TypeScript metadata, falling back to runtime parsing: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n }\n\n // Build and load the module\n const moduleText = await buildFile(filePath, {\n externalPackages: options.externalPackages,\n dynamicImportsToSkip: options.dynamicImportsToSkip,\n });\n loadModule({\n filename: filePath,\n moduleText,\n });\n\n // Select the appropriate function\n const selectedFunction = selectRolloutFunction(options.function);\n\n // If we have TypeScript metadata, match by span name and enrich params\n if (paramsMetadata) {\n logger.debug(`Available TS metadata keys: ${Array.from(paramsMetadata.keys()).join(', ')}`);\n logger.debug(\n `Looking for span name: ${selectedFunction.name} ` +\n `(runtime key: ${selectedFunction.exportName})`,\n );\n\n // Search for metadata by span name\n let foundMetadata: FunctionMetadata | null = null;\n for (const [exportName, metadata] of paramsMetadata.entries()) {\n logger.debug(\n `Checking ${exportName}: span name = ${metadata.name}, export name = ${exportName}`,\n );\n if (metadata.name === selectedFunction.name) {\n foundMetadata = metadata;\n logger.debug(`Match. Export name: ${exportName}, span name: ${metadata.name}`);\n break;\n }\n }\n\n if (foundMetadata) {\n selectedFunction.params = foundMetadata.params;\n logger.debug(`Using TypeScript metadata for span: ${selectedFunction.name}`);\n } else {\n logger.info(`No TypeScript metadata found for span name: ${selectedFunction.name}`);\n }\n }\n\n return {\n functionName: selectedFunction.name,\n params: selectedFunction.params || [],\n };\n};\n\n/**\n * Helper to execute subprocess commands\n */\nconst execCommand = async (\n command: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> => new Promise((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { spawn } = require('child_process');\n const child = spawn(command, args);\n let stdout = '';\n let stderr = '';\n\n child.stdout.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on('close', (code: number | null) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n } else {\n reject(new Error(`Command failed with code ${code}: ${stderr}`));\n }\n });\n\n child.on('error', (error: Error) => {\n reject(error);\n });\n});\n\n/**\n * Extracts JSON metadata from stdout that may contain other log statements\n * Looks for lines matching the protocol prefix and parses the JSON payload\n *\n * @param stdout - Raw stdout output that may contain logs and metadata\n * @returns Parsed JSON object\n * @throws Error if no valid metadata line is found or JSON parsing fails\n */\nexport const extractMetadataFromStdout = (stdout: string): any => {\n // Find all positions where LMNR_METADATA: appears\n const prefixPositions: number[] = [];\n let searchStart = 0;\n while (true) {\n const pos = stdout.indexOf(METADATA_PROTOCOL_PREFIX, searchStart);\n if (pos === -1) break;\n prefixPositions.push(pos);\n searchStart = pos + METADATA_PROTOCOL_PREFIX.length;\n }\n\n if (prefixPositions.length === 0) {\n // Fallback: try parsing the entire stdout as JSON (backward compatibility)\n try {\n return JSON.parse(stdout.trim());\n } catch {\n throw new Error(\n \"No metadata found in output. \" +\n \"Please make sure you are running the latest version of `lmnr` python package.\",\n );\n }\n }\n\n // Try to parse JSON starting from each prefix position\n // We'll keep the last successfully parsed JSON\n let lastValidJson: any = null;\n\n for (const pos of prefixPositions) {\n // Start after the prefix\n const startPos = pos + METADATA_PROTOCOL_PREFIX.length;\n const jsonText = stdout.slice(startPos).trim();\n\n // Try to parse the JSON by attempting increasingly shorter substrings\n // Strategy: Look for the end of the JSON object/array by finding matching braces\n // This handles the case where there might be additional text after the JSON\n\n // First, try parsing to the next newline (most common case)\n const nextNewline = stdout.indexOf('\\n', startPos);\n if (nextNewline !== -1) {\n const lineText = stdout.slice(startPos, nextNewline).trim();\n try {\n lastValidJson = JSON.parse(lineText);\n continue;\n } catch {\n // If that fails, we'll try the more complex approach below\n }\n }\n\n // More complex case: try to find the end of the JSON by counting braces\n // This handles multi-line JSON or JSON followed by more text\n try {\n let depth = 0;\n let inString = false;\n let escapeNext = false;\n let firstChar = -1;\n\n for (let i = 0; i < jsonText.length; i++) {\n const char = jsonText[i];\n\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\' && inString) {\n escapeNext = true;\n continue;\n }\n\n if (char === '\"') {\n inString = !inString;\n continue;\n }\n\n if (inString) continue;\n\n if (char === '{' || char === '[') {\n if (firstChar === -1) firstChar = i;\n depth++;\n } else if (char === '}' || char === ']') {\n depth--;\n if (depth === 0 && firstChar !== -1) {\n // Found the end of the JSON object/array\n const candidate = jsonText.slice(0, i + 1);\n lastValidJson = JSON.parse(candidate);\n break;\n }\n }\n }\n\n // If we didn't find a complete object, try parsing the whole thing\n if (depth !== 0 || firstChar === -1) {\n lastValidJson = JSON.parse(jsonText);\n }\n } catch {\n // If parsing fails, continue to the next prefix position\n continue;\n }\n }\n\n if (lastValidJson === null) {\n throw new Error(\n \"No valid metadata JSON found in output. \" +\n \"Please make sure you are running the latest version of `lmnr` python package.\",\n );\n }\n\n return lastValidJson;\n};\n\n/**\n * Discovers function metadata for Python files/modules by calling the lmnr Python CLI\n */\nconst discoverPythonMetadata = async (\n filePathOrModule: string,\n options: { pythonModule?: string; function?: string },\n): Promise<DiscoveredMetadata> => {\n logger.debug(`Discovering Python metadata for ${filePathOrModule}`);\n const args = ['discover'];\n\n // Determine if we're using a file path or module\n if (options.pythonModule) {\n // Module mode: lmnr discover --module src.myfile\n args.push('--module', options.pythonModule);\n } else {\n // Script mode: lmnr discover --file src/myfile.py\n args.push('--file', filePathOrModule);\n }\n\n // Add optional function name\n if (options.function) {\n args.push('--function', options.function);\n }\n\n try {\n // Execute: lmnr discover --file <path> | --module <module> [--function <name>]\n const result = await execCommand('lmnr', args);\n const response = extractMetadataFromStdout(result.stdout);\n\n // Response format: { \"name\": \"...\", \"params\": [...] }\n return {\n functionName: response.name,\n params: response.params || [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to discover Python metadata: ${errorMessage}`);\n if (errorMessage.toLowerCase().includes('command not found') ||\n errorMessage.includes('spawn lmnr ENOENT')) {\n logger.info(\n \"HINT: Make sure latest version of `lmnr` python package is installed. \" +\n \"`pip install --upgrade lmnr`, or if you are running this command from a virtual \" +\n \"environment, make sure to activate it. For `uv` users, rerun the command with `uv run`, \" +\n `e.g. \"uv run npx lmnr-cli dev ${filePathOrModule}\"`,\n );\n process.exit(1);\n }\n // Fallback\n const defaultName = options.pythonModule\n ? options.pythonModule.split('.').pop() || 'main'\n : path.basename(filePathOrModule, '.py');\n return {\n functionName: options.function || defaultName,\n params: [],\n };\n }\n};\n\n/**\n * Generic metadata discovery dispatcher that routes to language-specific implementations\n */\nexport const discoverFunctionMetadata = async (\n filePathOrModule: string,\n options: {\n pythonModule?: string;\n function?: string;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n },\n): Promise<DiscoveredMetadata> => {\n // If pythonModule is set, we're in Python module mode\n if (options.pythonModule) {\n return await discoverPythonMetadata(filePathOrModule, options);\n }\n\n // Otherwise check file extension\n const ext = path.extname(filePathOrModule);\n\n // TypeScript and JavaScript files use the same build/load/select process\n // For JS files, TypeScript metadata extraction will fail, but runtime param extraction works\n if (TS_JS_EXTENSIONS.includes(ext)) {\n return await discoverTypeScriptMetadata(filePathOrModule, options);\n }\n\n if (ext === '.py') {\n return await discoverPythonMetadata(filePathOrModule, options);\n }\n\n // Fallback for unsupported file types\n logger.warn(`No metadata discovery available for ${ext} files`);\n return {\n functionName: options.function || path.basename(filePathOrModule, ext),\n params: [],\n };\n};\n","import { LaminarClient } from '@lmnr-ai/client';\nimport {\n type CachedSpan,\n type RolloutHandshakeEvent,\n type RolloutParam,\n type RolloutRunEvent,\n type WorkerConfig,\n} from '@lmnr-ai/types';\nimport chokidar from 'chokidar';\nimport * as path from 'path';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { startCacheServer } from '../../cache-server';\nimport { createSSEClient, SSEClient } from '../../sse-client';\nimport { SubprocessManager } from '../../subprocess/executor';\nimport { initializeLogger } from '../../utils';\nimport { getWorkerCommand } from '../../worker-registry';\nimport {\n discoverFunctionMetadata,\n EXTENSIONS_TO_DISCOVER_METADATA,\n} from './metadata';\n\nconst logger = initializeLogger();\n\nexport interface DevOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n grpcPort?: number;\n function?: string;\n frontendPort?: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n command?: string;\n commandArgs?: string[];\n pythonModule?: string; // Python module path (e.g., 'src.myfile')\n}\n\nfunction newUUID(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return uuidv4();\n}\n\nfunction getFrontendUrl(baseUrl?: string, frontendPort?: number): string {\n let url = baseUrl ?? 'https://api.lmnr.ai';\n if (url === 'https://api.lmnr.ai') {\n url = 'https://www.laminar.sh';\n }\n url = url.replace(/\\/$/, '');\n\n if (/localhost|127\\.0\\.0\\.1/.test(url)) {\n const port = frontendPort ?? url.match(/:\\d{1,5}$/g)?.[0]?.slice(1) ?? 5667;\n url = url.replace(/:\\d{1,5}$/g, '');\n return `${url}:${port}`;\n }\n\n return url;\n}\n\n/**\n * Parses request arguments, attempting JSON parse for strings\n */\nconst tryParseArg = (arg: unknown) => {\n if (typeof arg === 'string') {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return JSON.parse(arg);\n } catch {\n return arg;\n }\n }\n return arg;\n};\n\n/**\n * Handles a run event from the backend\n */\nconst handleRunEvent = async (\n event: RolloutRunEvent,\n sessionId: string,\n filePathOrModule: string,\n client: LaminarClient,\n cacheServerPort: number,\n cache: Map<string, CachedSpan>,\n setMetadata: (metadata: any) => void,\n options: DevOptions,\n subprocessManager: SubprocessManager,\n): Promise<void> => {\n logger.debug('Received run event');\n\n const { trace_id, path_to_count, args: rawArgs, overrides } = event.data;\n\n const parsedArgs = Array.isArray(rawArgs)\n ? rawArgs.map(tryParseArg)\n : (Object.fromEntries(\n Object.entries(rawArgs).map(([key, value]) => [key, tryParseArg(value)]),\n ) as Record<string, any>);\n\n cache.clear();\n setMetadata({\n pathToCount: {},\n overrides: overrides,\n });\n\n try {\n // Check if we should populate cache from a previous trace\n if (!trace_id || trace_id.trim() === '') {\n logger.info('No spans in cache, starting fresh');\n } else {\n // Query spans from the backend to populate cache\n const paths = Object.keys(path_to_count || {});\n if (paths.length === 0) {\n logger.info('No spans to cache, starting fresh');\n } else {\n const query = `\n SELECT name, input, output, attributes, path\n FROM spans\n WHERE trace_id = {traceId:UUID}\n AND path IN {paths:String[]}\n ORDER BY start_time ASC\n `;\n\n logger.debug(`Querying spans from trace ${trace_id}...`);\n const spans = await client.sql.query(query, {\n traceId: trace_id,\n paths: paths,\n });\n logger.debug(`Received ${spans.length} spans from backend`);\n\n // Group spans by path and filter to first N per path\n const spansByPath: Record<string, any[]> = {};\n for (const span of spans) {\n const path = span.path as string;\n if (!spansByPath[path]) {\n spansByPath[path] = [];\n }\n spansByPath[path].push(span);\n }\n\n for (const [path, pathSpans] of Object.entries(spansByPath)) {\n const maxCount = path_to_count?.[path] || 0;\n const spansToCache = pathSpans.slice(0, maxCount);\n\n spansToCache.forEach((span, index) => {\n // Parse JSON fields\n let parsedInput = span.input;\n let parsedOutput = span.output;\n let parsedAttributes = span.attributes;\n\n try {\n parsedInput =\n typeof span.input === 'string' ? JSON.parse(span.input) : span.input;\n } catch {\n // Keep as string\n }\n\n try {\n parsedOutput =\n typeof span.output === 'string' ? span.output : JSON.stringify(span.output);\n } catch {\n parsedOutput = String(span.output);\n }\n\n try {\n parsedAttributes =\n typeof span.attributes === 'string'\n ? JSON.parse(span.attributes)\n : span.attributes;\n } catch {\n parsedAttributes = {};\n }\n\n const cachedSpan: CachedSpan = {\n name: span.name,\n input: parsedInput,\n output: parsedOutput,\n attributes: parsedAttributes,\n };\n\n const cacheKey = `${index}:${path}`;\n cache.set(cacheKey, cachedSpan);\n });\n\n logger.info(`Cached ${spansToCache.length} spans for path: ${path}`);\n }\n\n // Store metadata in cache server\n setMetadata({\n pathToCount: path_to_count || {},\n overrides,\n });\n }\n }\n\n // Parse baseUrl similar to how evaluations does it\n const baseUrl = options.baseUrl ?? process.env.LMNR_BASE_URL ?? 'https://api.lmnr.ai';\n const httpPort =\n options.port ??\n (baseUrl.match(/:\\d{1,5}$/g)\n ? parseInt(baseUrl.match(/:\\d{1,5}$/g)![0].slice(1))\n : 443);\n const grpcPort = options.grpcPort ?? 8443;\n\n // Prepare environment variables for child process\n const env: Record<string, string> = {\n LMNR_ROLLOUT_SESSION_ID: sessionId,\n LMNR_ROLLOUT_STATE_SERVER_ADDRESS: `http://localhost:${cacheServerPort}`,\n };\n\n // Prepare worker configuration\n const workerConfig: WorkerConfig = {\n filePath: options.pythonModule ? undefined : filePathOrModule,\n modulePath: options.pythonModule,\n functionName: options.function,\n args: parsedArgs,\n env,\n cacheServerPort,\n baseUrl,\n projectApiKey: options.projectApiKey,\n httpPort,\n grpcPort,\n externalPackages: options.externalPackages,\n dynamicImportsToSkip: options.dynamicImportsToSkip,\n };\n\n // Get worker command\n const workerCommand = options.command\n ? { command: options.command, args: options.commandArgs ?? [] }\n : getWorkerCommand(options.pythonModule ? undefined : filePathOrModule, options);\n\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'RUNNING',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n\n // Execute the rollout function in subprocess\n await subprocessManager.execute({\n command: workerCommand.command,\n args: workerCommand.args,\n config: workerConfig,\n });\n\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'FINISHED',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n } catch (error: any) {\n logger.error(`Error handling run event: ${error instanceof Error ? error.message : error}`);\n if (error instanceof Error && error.stack) {\n logger.error(error.stack);\n }\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: 'FINISHED',\n });\n } catch (error: any) {\n logger.error(\n `Error setting rollout session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n }\n};\n\n/**\n * Main dev command handler\n */\nexport async function runDev(filePath?: string, options: DevOptions = {}): Promise<void> {\n // Determine the actual path/module to use\n const isPythonModule = !!options.pythonModule;\n const filePathOrModule = filePath || options.pythonModule!;\n let didLogHandshake = false;\n\n // Generate session ID\n const sessionId = newUUID();\n\n // Initialize Laminar client\n const client = new LaminarClient({\n baseUrl: options.baseUrl,\n projectApiKey: options.projectApiKey,\n port: options.port,\n });\n\n // Start cache server\n logger.debug('Starting cache server...');\n const { port: cacheServerPort, server: cacheServer, cache, setMetadata } =\n await startCacheServer();\n logger.debug(`Cache server started on port ${cacheServerPort}`);\n\n // Create subprocess manager\n const subprocessManager = new SubprocessManager();\n\n // Get function metadata (name and params)\n let functionName = options.function;\n let params: RolloutParam[] = [];\n\n try {\n // Check if we should discover metadata\n const shouldDiscover =\n isPythonModule ||\n (filePath && EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath)));\n\n if (shouldDiscover) {\n logger.debug('Discovering rollout functions...');\n const metadata = await discoverFunctionMetadata(filePathOrModule, options);\n functionName = metadata.functionName;\n params = metadata.params;\n\n logger.info(`Serving function: ${functionName}`);\n logger.debug(`Function parameters: ${JSON.stringify(params, null, 2)}`);\n } else if (filePath) {\n // Unsupported file type\n functionName = options.function || path.basename(filePath, path.extname(filePath));\n logger.warn(`Metadata discovery not available for ${path.extname(filePath)} files`);\n }\n } catch (error) {\n logger.error(\n 'Failed to discover rollout functions: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n cacheServer.close();\n throw error;\n }\n\n // Setup file watcher for hot reload\n logger.debug('Setting up file watcher...');\n const watcher = chokidar.watch('.', {\n ignored: (path: string) => {\n const ignoredDirs = [\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n 'coverage',\n '.turbo',\n 'tmp',\n 'temp',\n 'venv',\n '.venv',\n 'virtualenv',\n '.virtualenv',\n '__pycache__',\n '.pytest_cache',\n '.ruff_cache',\n '.mypy_cache',\n '.cache',\n '.DS_Store',\n ];\n\n const pathSegments = path.split(/[/\\\\]/);\n if (pathSegments.some((segment) => ignoredDirs.includes(segment))) {\n return true;\n }\n\n if (path.endsWith('.log') || path.endsWith('.map')) {\n return true;\n }\n\n return false;\n },\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 100,\n },\n });\n\n // Create SSE client\n logger.debug('Setting up SSE client...');\n let sseClient: SSEClient | null = null;\n\n try {\n sseClient = createSSEClient({\n client,\n sessionId,\n params: params,\n name: functionName ?? '',\n });\n\n // Track if we're currently processing a run event (including metadata discovery)\n // This prevents race conditions during the build/load phase\n let currentRunPromise: Promise<void> | null = null;\n // Track if a stop was requested during the current run\n let stopRequested = false;\n\n // Register all event listeners BEFORE connecting\n sseClient.on('heartbeat', () => {\n logger.debug('Heartbeat received');\n });\n\n sseClient.on('run', (event: RolloutRunEvent) => {\n // Check if we're already processing a run (including metadata discovery)\n if (currentRunPromise !== null) {\n logger.warn('Already processing a run event, skipping new run');\n return;\n }\n\n // Create a promise chain that ensures metadata discovery completes before execution\n currentRunPromise = (async () => {\n try {\n // Reset stop flag at the start of each run\n stopRequested = false;\n\n // Check if a reload is scheduled and perform it before the run\n if (reloadScheduled) {\n logger.info('Reloading function metadata before run...');\n\n // Re-discover function metadata for supported file types\n // IMPORTANT: This builds and loads the module, so we must await it\n if (\n isPythonModule ||\n (filePath &&\n EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath)))\n ) {\n try {\n const metadata = await discoverFunctionMetadata(filePathOrModule, options);\n\n // Check if stop was requested during metadata discovery\n if (stopRequested) {\n logger.info('Run cancelled during metadata discovery');\n return;\n }\n\n logger.debug(`Updated function metadata: ${metadata.functionName}`);\n logger.debug(`Updated parameters: ${JSON.stringify(metadata.params, null, 2)}`);\n\n // Update the SSE client with new metadata\n if (sseClient) {\n sseClient.updateMetadata(metadata.params, metadata.functionName);\n logger.debug('Notified backend of metadata changes');\n }\n reloadScheduled = false;\n } catch (error: any) {\n logger.error(\n 'Failed to update function metadata: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n if (error instanceof Error && error.stack) {\n logger.debug(`Stack trace: ${error.stack}`);\n }\n // Don't proceed with run if metadata discovery failed\n // Keep reloadScheduled=true so next run will retry\n return;\n }\n } else {\n // No metadata discovery needed, clear the flag\n reloadScheduled = false;\n }\n }\n\n // Check if stop was requested before starting the subprocess\n if (stopRequested) {\n logger.info('Run cancelled before execution');\n return;\n }\n\n // After metadata reload completes (if needed), handle the run event\n await handleRunEvent(\n event,\n sessionId,\n filePathOrModule,\n client,\n cacheServerPort,\n cache,\n setMetadata,\n options,\n subprocessManager,\n );\n } catch (error) {\n logger.error(\n 'Unhandled error in run event handler: ' +\n (error instanceof Error ? error.message : String(error)),\n );\n } finally {\n // Clear the promise so the next run can proceed\n currentRunPromise = null;\n }\n })();\n });\n\n sseClient.on('handshake', (event: RolloutHandshakeEvent) => {\n const projectId = event.data.project_id;\n const sessionId = event.data.session_id;\n const frontendUrl = getFrontendUrl(options.baseUrl, options.frontendPort);\n if (!didLogHandshake) {\n logger.info(\n `View your session at ${frontendUrl}/project/${projectId}/rollout-sessions/${sessionId}`,\n );\n }\n didLogHandshake = true;\n });\n\n sseClient.on('error', (error: Error) => {\n logger.warn(`Error connecting to backend: ${error.message}`);\n });\n\n sseClient.on('reconnecting', () => {\n logger.info('Reconnecting to backend...');\n });\n\n sseClient.on('heartbeat_timeout', () => {\n logger.debug('Heartbeat timeout, reconnecting...');\n });\n\n sseClient.on('stop', () => {\n logger.debug('Stop event received');\n // Set the stop flag to abort any ongoing metadata discovery\n stopRequested = true;\n // Kill any running subprocess\n const wasKilled = subprocessManager.kill();\n // currentRunPromise will be cleared automatically when the run handler's\n // promise chain completes (see the finally block in the 'run' event handler above)\n if (wasKilled) {\n logger.info('Current run cancelled');\n }\n });\n\n // Setup file change handler for hot reload with debouncing\n let reloadTimeout: NodeJS.Timeout | null = null;\n let reloadScheduled = false;\n watcher.on('change', (changedPath: string) => {\n logger.info(`File changed: ${changedPath}, scheduling reload...`);\n\n // Clear any pending debounce timeout\n if (reloadTimeout) {\n clearTimeout(reloadTimeout);\n }\n\n // Debounce the reload flag to avoid multiple rapid file changes\n reloadTimeout = setTimeout(() => {\n logger.debug('Marking reload as scheduled for next run...');\n reloadTimeout = null;\n reloadScheduled = true;\n }, 100); // Wait 100ms after the last change before marking reload\n });\n\n // Handle graceful shutdown\n const shutdown = () => {\n logger.debug('Shutting down...');\n\n // Clear any pending reload timeout and scheduled reload\n if (reloadTimeout) {\n clearTimeout(reloadTimeout);\n reloadTimeout = null;\n }\n reloadScheduled = false;\n\n // Close file watcher\n logger.debug('Closing file watcher...');\n watcher\n .close()\n .catch((error: any) => {\n logger.error(\n `Failed to close file watcher: ${error instanceof Error ? error.message : error}`,\n );\n });\n\n // Kill any running subprocess\n subprocessManager.kill();\n\n // Delete the rollout session\n logger.debug('Deleting rollout session...');\n client.rolloutSessions\n .delete({ sessionId })\n .then(() => {\n if (sseClient) {\n sseClient.shutdown();\n }\n\n cacheServer.close(() => {\n logger.debug('Cache server closed');\n });\n process.exit(0);\n })\n .catch((error: any) => {\n logger.warn(\n `Failed to delete rollout session: ${error instanceof Error ? error.message : error}`,\n );\n process.exit(1);\n });\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n // Keep stdin open to prevent process from exiting\n process.stdin.resume();\n\n // Connect to backend and start listening\n logger.debug('Connecting to backend...');\n await sseClient.connectAndListen();\n } catch (error) {\n logger.error(\n 'Failed to start dev command: ' + (error instanceof Error ? error.message : String(error)),\n );\n\n // Try to delete the rollout session before exiting\n try {\n await client.rolloutSessions.delete({ sessionId });\n } catch {\n // Ignore delete errors during error cleanup\n }\n\n await watcher.close();\n cacheServer.close(() => {\n process.exit(1);\n });\n }\n}\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\n\nimport { version } from '../package.json';\nimport { runDev } from './commands/dev';\n\nasync function main() {\n const program = new Command();\n\n program\n .name('lmnr-cli')\n .description('CLI for Laminar AI rollout debugging')\n .version(version, '-v, --version', 'display version number');\n\n program\n .command('dev')\n .description('Start a rollout debugging session')\n .argument(\n '[file]',\n 'Path to file containing the agent function(s). Either `file` or `-m` must be provided.',\n )\n .option(\n '-m, --python-module <module>',\n 'Python module path (e.g., src.myfile). Either `file` or `-m` must be provided.',\n )\n .option(\n '--function <name>',\n 'Specific function to serve (if multiple rollout functions found)',\n )\n .option(\n '--project-api-key <key>',\n 'Project API key. If not provided, reads from LMNR_PROJECT_API_KEY env variable',\n )\n .option(\n '--base-url <url>',\n 'Base URL for the Laminar API. Defaults to https://api.lmnr.ai or LMNR_BASE_URL env variable',\n )\n .option('--port <port>', 'Port for the Laminar API. Defaults to 443', (val) =>\n parseInt(val, 10),\n )\n .option(\n '--grpc-port <port>',\n 'Port for the Laminar gRPC backend. Defaults to 8443',\n (val) => parseInt(val, 10),\n )\n .option(\n '--frontend-port <port>',\n 'Port for the Laminar frontend. Defaults to 5667',\n (val) => parseInt(val, 10),\n )\n .option(\n '--external-packages <packages...>',\n '[ADVANCED] List of packages to pass as external to esbuild. This will not link ' +\n 'the packages directly into the dev file, but will instead require them at runtime. ' +\n 'Read more: https://esbuild.github.io/api/#external',\n )\n .option(\n '--dynamic-imports-to-skip <modules...>',\n '[ADVANCED] List of module names to skip when encountered as dynamic imports. ' +\n 'These dynamic imports will resolve to an empty module to prevent build failures. ' +\n 'This is meant to skip the imports that are not used in the rollout itself.',\n )\n .option(\n '--command <command>',\n '[ADVANCED] Custom command to run the worker (e.g., python3, node)',\n )\n .option(\n '--command-args <args...>',\n '[ADVANCED] Arguments for the custom command',\n )\n .action(async (file: string | undefined, options) => {\n // Validation: must have either file or python-module, but not both\n if (!file && !options.pythonModule) {\n console.error('Error: Must provide either a file path or --python-module (-m) flag');\n process.exit(1);\n }\n if (file && options.pythonModule) {\n console.error('Error: Cannot specify both file path and --python-module (-m) flag');\n process.exit(1);\n }\n\n await runDev(file, options);\n })\n .addHelpText(\n 'after',\n `\nExamples:\n $ lmnr-cli dev agent.ts # TypeScript file\n $ lmnr-cli dev agent.py # Python file (script mode)\n $ lmnr-cli dev -m src.agent # Python module (module mode)\n $ lmnr-cli dev agent.ts --function myAgent # Specific function\n`,\n );\n\n await program.parseAsync();\n}\n\nmain().catch((err) => {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n});\n"],"x_google_ignoreList":[1,2],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lmnr-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for Laminar AI rollout debugging",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {
@@ -30,8 +30,8 @@
30
30
  "uuid": "^13.0.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@lmnr-ai/types": "0.8.6",
34
- "@lmnr-ai/client": "0.8.6"
33
+ "@lmnr-ai/client": "0.8.7",
34
+ "@lmnr-ai/types": "0.8.7"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@lmnr-ai/lmnr": "*"