lmnr-cli 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # lmnr-cli
2
2
 
3
- Language-agnostic CLI for Laminar AI rollout debugging.
3
+ Language-agnostic CLI for Laminar AI agent debugging.
4
4
 
5
5
  ## Overview
6
6
 
7
- The Laminar CLI is a pure orchestrator that coordinates rollout debugging sessions between your code and the Laminar backend. It is designed to be completely language-agnostic, delegating language-specific execution to worker processes.
7
+ The Laminar CLI is a pure orchestrator that coordinates debugging sessions between your code and the Laminar backend. It is designed to be completely language-agnostic, delegating language-specific execution to worker processes.
8
8
 
9
9
  ## Installation
10
10
 
@@ -28,7 +28,7 @@ lmnr-cli dev -m <python-module> [options]
28
28
  ### Options
29
29
 
30
30
  - `-m, --python-module <module>` - Python module path (e.g., `src.myfile`)
31
- - `--function <name>` - Specific function to serve (if multiple rollout functions found)
31
+ - `--function <name>` - Specific function to serve (if multiple entrypoint functions found)
32
32
  - `--project-api-key <key>` - Project API key (or set `LMNR_PROJECT_API_KEY` env variable)
33
33
  - `--base-url <url>` - Base URL for the Laminar API (default: https://api.lmnr.ai)
34
34
  - `--port <port>` - Port for the Laminar API (default: 443)
@@ -144,7 +144,7 @@ Any stdout without the `__LMNR_WORKER__:` prefix is considered user output (e.g.
144
144
 
145
145
  The CLI sets these environment variables for the worker:
146
146
 
147
- - `LMNR_ROLLOUT_SESSION_ID`: Session ID for this rollout run
147
+ - `LMNR_ROLLOUT_SESSION_ID`: Session ID for this debugger run
148
148
  - `LMNR_ROLLOUT_STATE_SERVER_ADDRESS`: Cache server URL (http://localhost:35667)
149
149
 
150
150
  ### Cache Server API
@@ -293,7 +293,7 @@ lmnr discover --module <module> [--function <name>]
293
293
 
294
294
  **Arguments:**
295
295
 
296
- - `--file <filepath>`: Path to the Python file containing rollout functions (script mode)
296
+ - `--file <filepath>`: Path to the Python file containing entrypoint functions (script mode)
297
297
  - `--module <module>`: Python module path like `src.myfile` (module mode)
298
298
  - `--function <name>`: (Optional) Specific function name to discover. If omitted, discover all.
299
299
 
@@ -366,7 +366,7 @@ npx lmnr-cli dev -m agents.customer_support --function run_agent
366
366
 
367
367
  ### Python Worker Requirements
368
368
 
369
- The Python `lmnr` package must implement a worker that executes rollout functions:
369
+ The Python `lmnr` package must implement a worker that executes entrypoint functions:
370
370
 
371
371
  ```bash
372
372
  python -m lmnr.cli.worker
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.4";
48
+ var version$1 = "0.1.6";
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.7";
395
+ var version = "0.8.13";
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}`;
@@ -1334,7 +1334,7 @@ var SubprocessManager = class {
1334
1334
  ] });
1335
1335
  this.currentProcess = child;
1336
1336
  return new Promise((resolve, reject) => {
1337
- let result = void 0;
1337
+ const result = void 0;
1338
1338
  let hasError = false;
1339
1339
  readline.createInterface({
1340
1340
  input: child.stdout,
@@ -1347,9 +1347,6 @@ var SubprocessManager = class {
1347
1347
  case "log":
1348
1348
  logger$2[message.level](message.message);
1349
1349
  break;
1350
- case "result":
1351
- result = message.data;
1352
- break;
1353
1350
  case "error":
1354
1351
  hasError = true;
1355
1352
  logger$2.error(`Worker error: ${message.error}`);
@@ -1357,7 +1354,8 @@ var SubprocessManager = class {
1357
1354
  break;
1358
1355
  }
1359
1356
  } catch {
1360
- logger$2.error(`Failed to parse worker protocol message: ${line}`);
1357
+ logger$2.debug("Failed to parse worker protocol message. Printing raw line");
1358
+ console.log(line.substring(WORKER_MESSAGE_PREFIX.length));
1361
1359
  }
1362
1360
  else console.log(line);
1363
1361
  });
@@ -1696,16 +1694,9 @@ const discoverPythonMetadata = async (filePathOrModule, options) => {
1696
1694
  };
1697
1695
  } catch (error) {
1698
1696
  const errorMessage = error instanceof Error ? error.message : String(error);
1699
- logger$1.error(`Failed to discover Python metadata: ${errorMessage}`);
1700
- if (errorMessage.toLowerCase().includes("command not found") || errorMessage.includes("spawn lmnr ENOENT")) {
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}"`);
1702
- process.exit(1);
1703
- }
1704
- const defaultName = options.pythonModule ? options.pythonModule.split(".").pop() || "main" : path.basename(filePathOrModule, ".py");
1705
- return {
1706
- functionName: options.function || defaultName,
1707
- params: []
1708
- };
1697
+ logger$1.error(`Error while loading Python file/module: ${errorMessage}`);
1698
+ if (errorMessage.toLowerCase().includes("command not found") || errorMessage.includes("spawn lmnr ENOENT")) 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
+ throw error;
1709
1700
  }
1710
1701
  };
1711
1702
  /**
@@ -1793,12 +1784,14 @@ const handleRunEvent = async (event, sessionId, filePathOrModule, client, cacheS
1793
1784
  const maxCount = path_to_count?.[path$2] || 0;
1794
1785
  const spansToCache = pathSpans.slice(0, maxCount);
1795
1786
  spansToCache.forEach((span, index) => {
1796
- let parsedInput = span.input;
1797
- let parsedOutput = span.output;
1798
- let parsedAttributes = span.attributes;
1787
+ let parsedInput;
1788
+ let parsedOutput;
1789
+ let parsedAttributes;
1799
1790
  try {
1800
1791
  parsedInput = typeof span.input === "string" ? JSON.parse(span.input) : span.input;
1801
- } catch {}
1792
+ } catch {
1793
+ parsedInput = span.input;
1794
+ }
1802
1795
  try {
1803
1796
  parsedOutput = typeof span.output === "string" ? span.output : JSON.stringify(span.output);
1804
1797
  } catch {
@@ -1857,7 +1850,7 @@ const handleRunEvent = async (event, sessionId, filePathOrModule, client, cacheS
1857
1850
  status: "RUNNING"
1858
1851
  });
1859
1852
  } catch (error) {
1860
- logger.error(`Error setting rollout session status: ${error instanceof Error ? error.message : error}`);
1853
+ logger.error(`Error setting debugger session status: ${error instanceof Error ? error.message : error}`);
1861
1854
  }
1862
1855
  await subprocessManager.execute({
1863
1856
  command: workerCommand.command,
@@ -1870,7 +1863,7 @@ const handleRunEvent = async (event, sessionId, filePathOrModule, client, cacheS
1870
1863
  status: "FINISHED"
1871
1864
  });
1872
1865
  } catch (error) {
1873
- logger.error(`Error setting rollout session status: ${error instanceof Error ? error.message : error}`);
1866
+ logger.error(`Error setting debugger session status: ${error instanceof Error ? error.message : error}`);
1874
1867
  }
1875
1868
  } catch (error) {
1876
1869
  logger.error(`Error handling run event: ${error instanceof Error ? error.message : error}`);
@@ -1881,7 +1874,7 @@ const handleRunEvent = async (event, sessionId, filePathOrModule, client, cacheS
1881
1874
  status: "FINISHED"
1882
1875
  });
1883
1876
  } catch (error$1) {
1884
- logger.error(`Error setting rollout session status: ${error$1 instanceof Error ? error$1.message : error$1}`);
1877
+ logger.error(`Error setting debugger session status: ${error$1 instanceof Error ? error$1.message : error$1}`);
1885
1878
  }
1886
1879
  }
1887
1880
  };
@@ -1906,7 +1899,7 @@ async function runDev(filePath, options = {}) {
1906
1899
  let params = [];
1907
1900
  try {
1908
1901
  if (isPythonModule || filePath && EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath))) {
1909
- logger.debug("Discovering rollout functions...");
1902
+ logger.debug("Discovering entrypoint functions...");
1910
1903
  const metadata = await discoverFunctionMetadata(filePathOrModule, options);
1911
1904
  functionName = metadata.functionName;
1912
1905
  params = metadata.params;
@@ -1917,7 +1910,7 @@ async function runDev(filePath, options = {}) {
1917
1910
  logger.warn(`Metadata discovery not available for ${path.extname(filePath)} files`);
1918
1911
  }
1919
1912
  } catch (error) {
1920
- logger.error("Failed to discover rollout functions: " + (error instanceof Error ? error.message : String(error)));
1913
+ logger.error("Failed to discover entrypoint functions: " + (error instanceof Error ? error.message : String(error)));
1921
1914
  cacheServer.close();
1922
1915
  throw error;
1923
1916
  }
@@ -2016,7 +2009,7 @@ async function runDev(filePath, options = {}) {
2016
2009
  const projectId = event.data.project_id;
2017
2010
  const sessionId$1 = event.data.session_id;
2018
2011
  const frontendUrl = getFrontendUrl(options.baseUrl, options.frontendPort);
2019
- if (!didLogHandshake) logger.info(`View your session at ${frontendUrl}/project/${projectId}/rollout-sessions/${sessionId$1}`);
2012
+ if (!didLogHandshake) logger.info(`View your session at ${frontendUrl}/project/${projectId}/debugger-sessions/${sessionId$1}`);
2020
2013
  didLogHandshake = true;
2021
2014
  });
2022
2015
  sseClient.on("error", (error) => {
@@ -2056,7 +2049,7 @@ async function runDev(filePath, options = {}) {
2056
2049
  logger.error(`Failed to close file watcher: ${error instanceof Error ? error.message : error}`);
2057
2050
  });
2058
2051
  subprocessManager.kill();
2059
- logger.debug("Deleting rollout session...");
2052
+ logger.debug("Deleting debugger session...");
2060
2053
  client.rolloutSessions.delete({ sessionId }).then(() => {
2061
2054
  if (sseClient) sseClient.shutdown();
2062
2055
  cacheServer.close(() => {
@@ -2064,7 +2057,7 @@ async function runDev(filePath, options = {}) {
2064
2057
  });
2065
2058
  process.exit(0);
2066
2059
  }).catch((error) => {
2067
- logger.warn(`Failed to delete rollout session: ${error instanceof Error ? error.message : error}`);
2060
+ logger.warn(`Failed to delete debugger session: ${error instanceof Error ? error.message : error}`);
2068
2061
  process.exit(1);
2069
2062
  });
2070
2063
  };
@@ -2089,8 +2082,8 @@ async function runDev(filePath, options = {}) {
2089
2082
  //#region src/index.ts
2090
2083
  async function main() {
2091
2084
  const program = new commander.Command();
2092
- program.name("lmnr-cli").description("CLI for Laminar AI rollout debugging").version(version$1, "-v, --version", "display version number");
2093
- program.command("dev").description("Start a rollout debugging session").argument("[file]", "Path to file containing the agent function(s). Either `file` or `-m` must be provided.").option("-m, --python-module <module>", "Python module path (e.g., src.myfile). Either `file` or `-m` must be provided.").option("--function <name>", "Specific function to serve (if multiple rollout functions found)").option("--project-api-key <key>", "Project API key. If not provided, reads from LMNR_PROJECT_API_KEY env variable").option("--base-url <url>", "Base URL for the Laminar API. Defaults to https://api.lmnr.ai or LMNR_BASE_URL env variable").option("--port <port>", "Port for the Laminar API. Defaults to 443", (val) => parseInt(val, 10)).option("--grpc-port <port>", "Port for the Laminar gRPC backend. Defaults to 8443", (val) => parseInt(val, 10)).option("--frontend-port <port>", "Port for the Laminar frontend. Defaults to 5667", (val) => parseInt(val, 10)).option("--external-packages <packages...>", "[ADVANCED] List of packages to pass as external to esbuild. This will not link the packages directly into the dev file, but will instead require them at runtime. Read more: https://esbuild.github.io/api/#external").option("--dynamic-imports-to-skip <modules...>", "[ADVANCED] List of module names to skip when encountered as dynamic imports. These dynamic imports will resolve to an empty module to prevent build failures. This is meant to skip the imports that are not used in the rollout itself.").option("--command <command>", "[ADVANCED] Custom command to run the worker (e.g., python3, node)").option("--command-args <args...>", "[ADVANCED] Arguments for the custom command").action(async (file, options) => {
2085
+ program.name("lmnr-cli").description("CLI for Laminar agent debugger").version(version$1, "-v, --version", "display version number");
2086
+ program.command("dev").description("Start a debugging session").argument("[file]", "Path to file containing the entrypoint function(s). Either `file` or `-m` must be provided.").option("-m, --python-module <module>", "Python module path (e.g., src.myfile). Either `file` or `-m` must be provided.").option("--function <name>", "Specific function to serve (if multiple entrypoint functions found)").option("--project-api-key <key>", "Project API key. If not provided, reads from LMNR_PROJECT_API_KEY env variable").option("--base-url <url>", "Base URL for the Laminar API. Defaults to https://api.lmnr.ai or LMNR_BASE_URL env variable").option("--port <port>", "Port for the Laminar API. Defaults to 443", (val) => parseInt(val, 10)).option("--grpc-port <port>", "Port for the Laminar gRPC backend. Defaults to 8443", (val) => parseInt(val, 10)).option("--frontend-port <port>", "Port for the Laminar frontend. Defaults to 5667", (val) => parseInt(val, 10)).option("--external-packages <packages...>", "[ADVANCED] List of packages to pass as external to esbuild. This will not link the packages directly into the dev file, but will instead require them at runtime. Read more: https://esbuild.github.io/api/#external").option("--dynamic-imports-to-skip <modules...>", "[ADVANCED] List of module names to skip when encountered as dynamic imports. These dynamic imports will resolve to an empty module to prevent build failures. This is meant to skip the imports that are not used in the entrypoint function itself.").option("--command <command>", "[ADVANCED] Custom command to run the worker (e.g., python3, node)").option("--command-args <args...>", "[ADVANCED] Arguments for the custom command").action(async (file, options) => {
2094
2087
  if (!file && !options.pythonModule) {
2095
2088
  console.error("Error: Must provide either a file path or --python-module (-m) flag");
2096
2089
  process.exit(1);
@@ -1 +1 @@
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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"}
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.13\";\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 const 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\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.debug(\"Failed to parse worker protocol message. Printing raw line\");\n console.log(line.substring(WORKER_MESSAGE_PREFIX.length));\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(`Error while loading Python file/module: ${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 }\n throw error;\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 (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\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]) => [\n key,\n tryParseArg(value),\n ]),\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;\n let parsedOutput;\n let parsedAttributes;\n\n try {\n parsedInput =\n typeof span.input === \"string\"\n ? JSON.parse(span.input)\n : span.input;\n } catch {\n parsedInput = span.input;\n }\n\n try {\n parsedOutput =\n typeof span.output === \"string\"\n ? span.output\n : 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 =\n 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(\n options.pythonModule ? undefined : filePathOrModule,\n options,\n );\n\n try {\n await client.rolloutSessions.setStatus({\n sessionId,\n status: \"RUNNING\",\n });\n } catch (error: any) {\n logger.error(\n `Error setting debugger session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n\n // Execute the entrypoint 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 debugger session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n } catch (error: any) {\n logger.error(\n `Error handling run event: ${error instanceof Error ? error.message : error}`,\n );\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 debugger session status: ${error instanceof Error ? error.message : error}`,\n );\n }\n }\n};\n\n/**\n * Main dev command handler\n */\nexport async function runDev(\n filePath?: string,\n options: DevOptions = {},\n): 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 {\n port: cacheServerPort,\n server: cacheServer,\n cache,\n 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 &&\n EXTENSIONS_TO_DISCOVER_METADATA.includes(path.extname(filePath)));\n\n if (shouldDiscover) {\n logger.debug(\"Discovering entrypoint functions...\");\n const metadata = await discoverFunctionMetadata(\n filePathOrModule,\n options,\n );\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 =\n options.function || path.basename(filePath, path.extname(filePath));\n logger.warn(\n `Metadata discovery not available for ${path.extname(filePath)} files`,\n );\n }\n } catch (error) {\n logger.error(\n \"Failed to discover entrypoint 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(\n path.extname(filePath),\n ))\n ) {\n try {\n const metadata = await discoverFunctionMetadata(\n filePathOrModule,\n options,\n );\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(\n `Updated function metadata: ${metadata.functionName}`,\n );\n logger.debug(\n `Updated parameters: ${JSON.stringify(metadata.params, null, 2)}`,\n );\n\n // Update the SSE client with new metadata\n if (sseClient) {\n sseClient.updateMetadata(\n metadata.params,\n metadata.functionName,\n );\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}/debugger-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.close().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 debugger session\n logger.debug(\"Deleting debugger 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 debugger 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: \" +\n (error instanceof Error ? error.message : String(error)),\n );\n\n // Try to delete the debugger 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 agent debugger')\n .version(version, '-v, --version', 'display version number');\n\n program\n .command('dev')\n .description('Start a debugging session')\n .argument(\n '[file]',\n 'Path to file containing the entrypoint 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 entrypoint 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 entrypoint function 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CEAA,MAAM,KAAK,QAAQ,KAAK;CACxB,MAAMA,SAAO,QAAQ,OAAO;CAC5B,MAAM,KAAK,QAAQ,KAAK;CACxB,MAAMC,WAAS,QAAQ,SAAS;CAGhC,MAAM,4BAAsB;CAG5B,MAAM,OAAO;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAGD,SAAS,gBAAiB;AACxB,SAAO,KAAK,KAAK,MAAM,KAAK,QAAQ,GAAG,KAAK,OAAO;;CAGrD,SAAS,aAAc,OAAO;AAC5B,MAAI,OAAO,UAAU,SACnB,QAAO,CAAC;GAAC;GAAS;GAAK;GAAM;GAAO;GAAG,CAAC,SAAS,MAAM,aAAa,CAAC;AAEvE,SAAO,QAAQ,MAAM;;CAGvB,SAAS,eAAgB;AACvB,SAAO,QAAQ,OAAO;;CAGxB,SAAS,IAAK,MAAM;AAClB,SAAO,cAAc,GAAG,UAAU,KAAK,WAAW;;CAGpD,MAAM,OAAO;CAGb,SAAS,MAAO,KAAK;EACnB,MAAM,MAAM,EAAE;EAGd,IAAI,QAAQ,IAAI,UAAU;AAG1B,UAAQ,MAAM,QAAQ,WAAW,KAAK;EAEtC,IAAI;AACJ,UAAQ,QAAQ,KAAK,KAAK,MAAM,KAAK,MAAM;GACzC,MAAM,MAAM,MAAM;GAGlB,IAAI,QAAS,MAAM,MAAM;AAGzB,WAAQ,MAAM,MAAM;GAGpB,MAAM,aAAa,MAAM;AAGzB,WAAQ,MAAM,QAAQ,0BAA0B,KAAK;AAGrD,OAAI,eAAe,MAAK;AACtB,YAAQ,MAAM,QAAQ,QAAQ,KAAK;AACnC,YAAQ,MAAM,QAAQ,QAAQ,KAAK;;AAIrC,OAAI,OAAO;;AAGb,SAAO;;CAGT,SAAS,YAAa,SAAS;AAC7B,YAAU,WAAW,EAAE;EAEvB,MAAM,YAAY,WAAW,QAAQ;AACrC,UAAQ,OAAO;EACf,MAAM,SAAS,aAAa,aAAa,QAAQ;AACjD,MAAI,CAAC,OAAO,QAAQ;GAClB,MAAM,sBAAM,IAAI,MAAM,8BAA8B,UAAU,wBAAwB;AACtF,OAAI,OAAO;AACX,SAAM;;EAKR,MAAM,OAAO,WAAW,QAAQ,CAAC,MAAM,IAAI;EAC3C,MAAM,SAAS,KAAK;EAEpB,IAAI;AACJ,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAC1B,KAAI;GAKF,MAAM,QAAQ,cAAc,QAHhB,KAAK,GAAG,MAAM,CAGc;AAGxC,eAAY,aAAa,QAAQ,MAAM,YAAY,MAAM,IAAI;AAE7D;WACO,OAAO;AAEd,OAAI,IAAI,KAAK,OACX,OAAM;;AAOZ,SAAO,aAAa,MAAM,UAAU;;CAGtC,SAAS,MAAO,SAAS;AACvB,UAAQ,MAAM,WAAW,QAAQ,UAAU,UAAU;;CAGvD,SAAS,OAAQ,SAAS;AACxB,UAAQ,IAAI,WAAW,QAAQ,WAAW,UAAU;;CAGtD,SAAS,KAAM,SAAS;AACtB,UAAQ,IAAI,WAAW,QAAQ,IAAI,UAAU;;CAG/C,SAAS,WAAY,SAAS;AAE5B,MAAI,WAAW,QAAQ,cAAc,QAAQ,WAAW,SAAS,EAC/D,QAAO,QAAQ;AAIjB,MAAI,QAAQ,IAAI,cAAc,QAAQ,IAAI,WAAW,SAAS,EAC5D,QAAO,QAAQ,IAAI;AAIrB,SAAO;;CAGT,SAAS,cAAe,QAAQ,WAAW;EAEzC,IAAI;AACJ,MAAI;AACF,SAAM,IAAI,IAAI,UAAU;WACjB,OAAO;AACd,OAAI,MAAM,SAAS,mBAAmB;IACpC,MAAM,sBAAM,IAAI,MAAM,6IAA6I;AACnK,QAAI,OAAO;AACX,UAAM;;AAGR,SAAM;;EAIR,MAAM,MAAM,IAAI;AAChB,MAAI,CAAC,KAAK;GACR,MAAM,sBAAM,IAAI,MAAM,uCAAuC;AAC7D,OAAI,OAAO;AACX,SAAM;;EAIR,MAAM,cAAc,IAAI,aAAa,IAAI,cAAc;AACvD,MAAI,CAAC,aAAa;GAChB,MAAM,sBAAM,IAAI,MAAM,+CAA+C;AACrE,OAAI,OAAO;AACX,SAAM;;EAIR,MAAM,iBAAiB,gBAAgB,YAAY,aAAa;EAChE,MAAM,aAAa,OAAO,OAAO;AACjC,MAAI,CAAC,YAAY;GACf,MAAM,sBAAM,IAAI,MAAM,2DAA2D,eAAe,2BAA2B;AAC3H,OAAI,OAAO;AACX,SAAM;;AAGR,SAAO;GAAE;GAAY;GAAK;;CAG5B,SAAS,WAAY,SAAS;EAC5B,IAAI,oBAAoB;AAExB,MAAI,WAAW,QAAQ,QAAQ,QAAQ,KAAK,SAAS,EACnD,KAAI,MAAM,QAAQ,QAAQ,KAAK,EAC7B;QAAK,MAAM,YAAY,QAAQ,KAC7B,KAAI,GAAG,WAAW,SAAS,CACzB,qBAAoB,SAAS,SAAS,SAAS,GAAG,WAAW,GAAG,SAAS;QAI7E,qBAAoB,QAAQ,KAAK,SAAS,SAAS,GAAG,QAAQ,OAAO,GAAG,QAAQ,KAAK;MAGvF,qBAAoBD,OAAK,QAAQ,QAAQ,KAAK,EAAE,aAAa;AAG/D,MAAI,GAAG,WAAW,kBAAkB,CAClC,QAAO;AAGT,SAAO;;CAGT,SAAS,aAAc,SAAS;AAC9B,SAAO,QAAQ,OAAO,MAAMA,OAAK,KAAK,GAAG,SAAS,EAAE,QAAQ,MAAM,EAAE,CAAC,GAAG;;CAG1E,SAAS,aAAc,SAAS;EAC9B,MAAM,QAAQ,aAAa,QAAQ,IAAI,uBAAwB,WAAW,QAAQ,MAAO;EACzF,MAAM,QAAQ,aAAa,QAAQ,IAAI,uBAAwB,WAAW,QAAQ,MAAO;AAEzF,MAAI,SAAS,CAAC,MACZ,MAAK,wCAAwC;EAG/C,MAAM,SAAS,aAAa,YAAY,QAAQ;EAEhD,IAAI,aAAa,QAAQ;AACzB,MAAI,WAAW,QAAQ,cAAc,KACnC,cAAa,QAAQ;AAGvB,eAAa,SAAS,YAAY,QAAQ,QAAQ;AAElD,SAAO,EAAE,QAAQ;;CAGnB,SAAS,aAAc,SAAS;EAC9B,MAAM,aAAaA,OAAK,QAAQ,QAAQ,KAAK,EAAE,OAAO;EACtD,IAAI,WAAW;EACf,IAAI,aAAa,QAAQ;AACzB,MAAI,WAAW,QAAQ,cAAc,KACnC,cAAa,QAAQ;EAEvB,IAAI,QAAQ,aAAa,WAAW,uBAAwB,WAAW,QAAQ,MAAO;EACtF,IAAI,QAAQ,aAAa,WAAW,uBAAwB,WAAW,QAAQ,MAAO;AAEtF,MAAI,WAAW,QAAQ,SACrB,YAAW,QAAQ;WAEf,MACF,QAAO,qDAAqD;EAIhE,IAAI,cAAc,CAAC,WAAW;AAC9B,MAAI,WAAW,QAAQ,KACrB,KAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAC9B,eAAc,CAAC,aAAa,QAAQ,KAAK,CAAC;OACrC;AACL,iBAAc,EAAE;AAChB,QAAK,MAAM,YAAY,QAAQ,KAC7B,aAAY,KAAK,aAAa,SAAS,CAAC;;EAO9C,IAAI;EACJ,MAAM,YAAY,EAAE;AACpB,OAAK,MAAMA,UAAQ,YACjB,KAAI;GAEF,MAAM,SAAS,aAAa,MAAM,GAAG,aAAaA,QAAM,EAAE,UAAU,CAAC,CAAC;AAEtE,gBAAa,SAAS,WAAW,QAAQ,QAAQ;WAC1C,GAAG;AACV,OAAI,MACF,QAAO,kBAAkBA,OAAK,GAAG,EAAE,UAAU;AAE/C,eAAY;;EAIhB,MAAM,YAAY,aAAa,SAAS,YAAY,WAAW,QAAQ;AAGvE,UAAQ,aAAa,WAAW,uBAAuB,MAAM;AAC7D,UAAQ,aAAa,WAAW,uBAAuB,MAAM;AAE7D,MAAI,SAAS,CAAC,OAAO;GACnB,MAAM,YAAY,OAAO,KAAK,UAAU,CAAC;GACzC,MAAM,aAAa,EAAE;AACrB,QAAK,MAAM,YAAY,YACrB,KAAI;IACF,MAAM,WAAWA,OAAK,SAAS,QAAQ,KAAK,EAAE,SAAS;AACvD,eAAW,KAAK,SAAS;YAClB,GAAG;AACV,QAAI,MACF,QAAO,kBAAkB,SAAS,GAAG,EAAE,UAAU;AAEnD,gBAAY;;AAIhB,QAAK,kBAAkB,UAAU,SAAS,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,WAAW,eAAe,GAAG,GAAG;;AAGxG,MAAI,UACF,QAAO;GAAE,QAAQ;GAAW,OAAO;GAAW;MAE9C,QAAO,EAAE,QAAQ,WAAW;;CAKhC,SAAS,OAAQ,SAAS;AAExB,MAAI,WAAW,QAAQ,CAAC,WAAW,EACjC,QAAO,aAAa,aAAa,QAAQ;EAG3C,MAAM,YAAY,WAAW,QAAQ;AAGrC,MAAI,CAAC,WAAW;AACd,SAAM,+DAA+D,UAAU,+BAA+B;AAE9G,UAAO,aAAa,aAAa,QAAQ;;AAG3C,SAAO,aAAa,aAAa,QAAQ;;CAG3C,SAAS,QAAS,WAAW,QAAQ;EACnC,MAAM,MAAM,OAAO,KAAK,OAAO,MAAM,IAAI,EAAE,MAAM;EACjD,IAAI,aAAa,OAAO,KAAK,WAAW,SAAS;EAEjD,MAAM,QAAQ,WAAW,SAAS,GAAG,GAAG;EACxC,MAAM,UAAU,WAAW,SAAS,IAAI;AACxC,eAAa,WAAW,SAAS,IAAI,IAAI;AAEzC,MAAI;GACF,MAAM,SAASC,SAAO,iBAAiB,eAAe,KAAK,MAAM;AACjE,UAAO,WAAW,QAAQ;AAC1B,UAAO,GAAG,OAAO,OAAO,WAAW,GAAG,OAAO,OAAO;WAC7C,OAAO;GACd,MAAM,UAAU,iBAAiB;GACjC,MAAM,mBAAmB,MAAM,YAAY;GAC3C,MAAM,mBAAmB,MAAM,YAAY;AAE3C,OAAI,WAAW,kBAAkB;IAC/B,MAAM,sBAAM,IAAI,MAAM,8DAA8D;AACpF,QAAI,OAAO;AACX,UAAM;cACG,kBAAkB;IAC3B,MAAM,sBAAM,IAAI,MAAM,kDAAkD;AACxE,QAAI,OAAO;AACX,UAAM;SAEN,OAAM;;;CAMZ,SAAS,SAAU,YAAY,QAAQ,UAAU,EAAE,EAAE;EACnD,MAAM,QAAQ,QAAQ,WAAW,QAAQ,MAAM;EAC/C,MAAM,WAAW,QAAQ,WAAW,QAAQ,SAAS;EACrD,MAAM,YAAY,EAAE;AAEpB,MAAI,OAAO,WAAW,UAAU;GAC9B,MAAM,sBAAM,IAAI,MAAM,iFAAiF;AACvG,OAAI,OAAO;AACX,SAAM;;AAIR,OAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,OAAO,UAAU,eAAe,KAAK,YAAY,IAAI,EAAE;AACzD,OAAI,aAAa,MAAM;AACrB,eAAW,OAAO,OAAO;AACzB,cAAU,OAAO,OAAO;;AAG1B,OAAI,MACF,KAAI,aAAa,KACf,QAAO,IAAI,IAAI,0CAA0C;OAEzD,QAAO,IAAI,IAAI,8CAA8C;SAG5D;AACL,cAAW,OAAO,OAAO;AACzB,aAAU,OAAO,OAAO;;AAI5B,SAAO;;CAGT,MAAM,eAAe;EACnB;EACA;EACA;EACA;EACA;EACA;EACA;EACD;AAED,QAAO,QAAQ,eAAe,aAAa;AAC3C,QAAO,QAAQ,eAAe,aAAa;AAC3C,QAAO,QAAQ,cAAc,aAAa;AAC1C,QAAO,QAAQ,SAAS,aAAa;AACrC,QAAO,QAAQ,UAAU,aAAa;AACtC,QAAO,QAAQ,QAAQ,aAAa;AACpC,QAAO,QAAQ,WAAW,aAAa;AAEvC,QAAO,UAAU;;;;;;AC1ajB,IAAI,UAAU;AAId,SAAS,iBAAiB;AACzB,KAAI,OAAO,YAAY,eAAe,QAAQ,YAAY,QAAQ,SAAS,KAAM,QAAO,QAAQ,QAAQ,SAAS;AACjH,KAAI,OAAO,cAAc,eAAe,UAAU,UAAW,QAAO,WAAW,UAAU;AACzF,QAAO;;AAKR,IAAI,eAAe,MAAM;CACxB,YAAY,aAAa,eAAe;AACvC,OAAK,cAAc;AACnB,OAAK,gBAAgB;;CAEtB,UAAU;AACT,SAAO;GACN,eAAe,UAAU,KAAK;GAC9B,gBAAgB;GAChB,QAAQ;GACR;;CAEF,MAAM,YAAY,UAAU;EAC3B,MAAM,WAAW,MAAM,SAAS,MAAM;AACtC,QAAM,IAAI,MAAM,GAAG,SAAS,OAAO,GAAG,WAAW;;;AAMnD,IAAI,wBAAwB,cAAc,aAAa;CACtD,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;CAElC,MAAM,KAAK,EAAE,WAAW,SAAS,oBAAU;EAC1C,MAAM,UAAU;GACf;GACA;GACA;GACA,QAAQ,gBAAgB,IAAI;GAC5B,YAAY;GACZ;EACD,MAAM,aAAa,KAAK,UAAU,QAAQ;EAC1C,MAAM,mBAAmB,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,MAAM,oBAAoB,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,kBAAkB,OAAO,CAAC;EACjI,MAAM,iBAAiB,MAAM,IAAI,SAAS,iBAAiB,CAAC,aAAa;EACzE,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,+BAA+B;GAC9E,QAAQ;GACR,SAAS;IACR,GAAG,KAAK,SAAS;IACjB,oBAAoB;IACpB;GACD,MAAM;GACN,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;;AAMpD,SAASC,mBAAiB,SAAS;CAClC,MAAM,WAAW,SAAS,YAAY;CACtC,MAAM,QAAQ,SAAS,SAAS,QAAQ,IAAI,gBAAgB,aAAa,EAAE,MAAM,IAAI;AACrF,0BAAY,EAAE,OAAO,8BAAa;EACjC;EACA,cAAc;EACd,CAAC,CAAC;;AAEJ,MAAMC,aAAWD,oBAAkB;AACnC,MAAM,gBAAgB,OAAO,iEAAiE,KAAK,GAAG;AACtG,MAAME,kBAAgB;AACrB,KAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY,QAAO,OAAO,YAAY;KACnG,sBAAW;;AAEjB,MAAM,oBAAoB,WAAW;CACpC,IAAI,KAAK,OAAO,aAAa;AAC7B,KAAI,GAAG,WAAW,KAAK,CAAE,MAAK,GAAG,MAAM,EAAE;AACzC,KAAI,GAAG,WAAW,GAAI,YAAS,KAAK,WAAW,OAAO,uEAAuE;AAC7H,KAAI,CAAC,cAAc,KAAK,GAAG,EAAE;AAC5B,aAAS,MAAM,WAAW,OAAO,+DAA+D;AAChG,SAAOA,WAAS;;AAEjB,QAAO,GAAG,SAAS,IAAI,IAAI,CAAC,QAAQ,wEAAwE,iBAAiB;;AAE9H,MAAM,qBAAqB,YAAY;CACtC,IAAI,KAAK,QAAQ,aAAa;AAC9B,KAAI,GAAG,WAAW,KAAK,CAAE,MAAK,GAAG,MAAM,EAAE;AACzC,KAAI,GAAG,WAAW,GAAI,YAAS,KAAK,YAAY,QAAQ,wEAAwE;AAChI,KAAI,CAAC,cAAc,KAAK,GAAG,EAAE;AAC5B,aAAS,MAAM,YAAY,QAAQ,+DAA+D;AAClG,SAAOA,WAAS;;AAEjB,QAAO,GAAG,QAAQ,wEAAwE,iBAAiB;;AAE5G,MAAM,gBAAgB,OAAO,WAAW;AACvC,KAAI,UAAU,QAAQ,UAAU,KAAK,EAAG,QAAO;CAC/C,MAAM,MAAM,KAAK,UAAU,MAAM;AACjC,KAAI,IAAI,UAAU,OAAQ,QAAO;AACjC,QAAO,IAAI,MAAM,GAAG,OAAO,GAAG;;AAE/B,MAAM,WAAW,YAAY;CAC5B,MAAM,UAAU,QAAQ,IAAI,YAAY;CACxC,MAAM,SAAS,QAAQ,KAAK;CAC5B,MAAM,WAAW;EAChB;EACA;EACA,QAAQ;EACR,QAAQ,QAAQ;EAChB;CACD,MAAM,WAAW,QAAQ,IAAI,kBAAkB;CAC/C,MAAM,UAAU,CAAC,SAAS,QAAQ,CAAC,SAAS,SAAS,MAAM,CAAC,aAAa,CAAC;CAC1E,MAAM,QAAQ,SAAS,SAAS,CAAC;AACjC,yBAAO;EACN,MAAM,SAAS,SAAS,SAAS,KAAK,YAAY,KAAK,QAAQ,QAAQ,QAAQ,CAAC;EAChF;EACA,CAAC;;AAKH,MAAMC,aAAWH,oBAAkB;AACnC,MAAM,6BAA6B;AACnC,MAAM,kCAAkC;AACxC,IAAI,mBAAmB,cAAc,aAAa;CACjD,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;;;;;;CAOlC,MAAM,eAAe;EACpB,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,gBAAgB;GAC/D,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,SAAS,MAAM;;;;;;;;CAQvB,MAAM,iBAAiB,MAAM;EAC5B,MAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;EAC5C,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,gBAAgB,OAAO,UAAU,IAAI;GACpF,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,SAAS,MAAM;;;;;;;;;;;;;CAavB,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,YAAY,iCAAiC,gBAAgB,SAAS;AACpG,MAAI,CAAC,QAAQ,CAAC,GAAI,OAAM,IAAI,MAAM,qCAAqC;AACvE,MAAI,QAAQ,GAAI,OAAM,IAAI,MAAM,0CAA0C;AAC1E,MAAI,iBAAiB,CAAC,KAAM,OAAM,IAAI,MAAM,oDAAoD;EAChG,MAAM,aAAa,OAAO,EAAE,MAAM,GAAG,EAAE,WAAW,IAAI;EACtD,MAAM,eAAe,KAAK,KAAK,OAAO,SAAS,UAAU;EACzD,IAAI;AACJ,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW;GAClD,MAAM,WAAW,KAAK,MAAM,IAAI,UAAU,GAAG;AAC7C,cAAS,MAAM,iBAAiB,SAAS,MAAM,eAAe;GAC9D,MAAM,QAAQ,OAAO,MAAM,GAAG,IAAI,UAAU;GAC5C,MAAM,gBAAgB,MAAM,MAAM,KAAK,cAAc,2BAA2B;IAC/E,QAAQ;IACR,SAAS,KAAK,SAAS;IACvB,MAAM,KAAK,UAAU;KACpB,GAAG;KACH,YAAY,MAAM,KAAK,WAAW;MACjC,MAAM,MAAM;MACZ,QAAQ,MAAM,UAAU,EAAE;MAC1B,UAAU,MAAM,YAAY,EAAE;MAC9B,EAAE;KACH;KACA,CAAC;IACF,CAAC;AACF,OAAI,cAAc,WAAW,OAAO,cAAc,WAAW,IAAK,OAAM,KAAK,YAAY,cAAc;AACvG,cAAW,MAAM,cAAc,MAAM;;AAEtC,SAAO;;;;;;;;;;;;CAYR,MAAM,KAAK,EAAE,MAAM,IAAI,QAAQ,4BAA4B,SAAS,KAAK;AACxE,MAAI,CAAC,QAAQ,CAAC,GAAI,OAAM,IAAI,MAAM,qCAAqC;AACvE,MAAI,QAAQ,GAAI,OAAM,IAAI,MAAM,0CAA0C;EAC1E,MAAM,YAAY;GACjB,QAAQ,OAAO,UAAU;GACzB,OAAO,MAAM,UAAU;GACvB;AACD,MAAI,KAAM,WAAU,OAAO;MACtB,WAAU,YAAY;EAC3B,MAAM,SAAS,IAAI,gBAAgB,UAAU;EAC7C,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,2BAA2B,OAAO,UAAU,IAAI;GAC/F,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,SAAS,MAAM;;;AAMxB,MAAMI,WAASJ,oBAAkB;AACjC,MAAM,+CAA+C;AACrD,IAAI,gBAAgB,cAAc,aAAa;CAC9C,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;;;;;;;;;CAUlC,MAAM,KAAK,MAAM,WAAW,UAAU;EACrC,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,aAAa;GAC5D,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU;IACpB,MAAM,QAAQ;IACd,WAAW,aAAa;IACxB,UAAU,YAAY;IACtB,CAAC;GACF,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,SAAS,MAAM;;;;;;;;;;CAUvB,MAAM,OAAO,MAAM;AAClB,UAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,WAAW,MAAM,SAAS,EAAE;;;;;;CAMvE,MAAM,iBAAiB,MAAM,WAAW,UAAU;AACjD,UAAQ,MAAM,KAAK,KAAK,MAAM,WAAW,SAAS,EAAE;;;;;;;;;;;;;;CAcrD,MAAM,gBAAgB,EAAE,QAAQ,MAAM,QAAQ,UAAU,OAAO,WAAW;EACzE,MAAM,cAAcE,WAAS;EAC7B,MAAM,mBAAmB;GACxB,IAAI;GACJ;GACA;GACA,OAAO,SAAS;GAChB,SAAS,WAAWA,WAAS;GAC7B,gBAAgBA,WAAS;GACzB;GACA;AACD,QAAM,KAAK,eAAe;GACzB;GACA,YAAY,CAAC,iBAAiB;GAC9B,CAAC;AACF,SAAO;;;;;;;;;;;;CAYR,MAAM,gBAAgB,EAAE,QAAQ,aAAa,QAAQ,kBAAkB;EACtE,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,aAAa,OAAO,cAAc,eAAe;GAChG,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU;IACpB;IACA;IACA,CAAC;GACF,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;;;;;;;;;;CAWnD,MAAM,eAAe,EAAE,QAAQ,YAAY,aAAa;EACvD,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,aAAa,OAAO,cAAc;GACjF,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU;IACpB,QAAQ,WAAW,KAAK,OAAO;KAC9B,GAAG;KACH,MAAM,aAAa,EAAE,MAAM,6CAA6C;KACxE,QAAQ,aAAa,EAAE,QAAQ,6CAA6C;KAC5E,gBAAgB,aAAa,EAAE,gBAAgB,6CAA6C;KAC5F,EAAE;IACH,WAAW,aAAa;IACxB,CAAC;GACF,CAAC;AACF,MAAI,SAAS,WAAW,IAAK,QAAO,MAAM,KAAK,oBAAoB;GAClE;GACA;GACA;GACA,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;;;;;;;;;;;CAYnD,MAAM,cAAc,EAAE,aAAa,QAAQ,SAAS;AACnD,WAAO,KAAK,2EAA2E;EACvF,MAAM,SAAS,IAAI,gBAAgB;GAClC,MAAM;GACN,QAAQ,OAAO,UAAU;GACzB,OAAO,MAAM,UAAU;GACvB,CAAC;EACF,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,2BAA2B,OAAO,UAAU,IAAI;GAC/F,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,MAAM,SAAS,MAAM;;CAE7B,MAAM,oBAAoB,EAAE,QAAQ,YAAY,WAAW,aAAa,IAAI,gBAAgB,gDAAgD;EAC3I,IAAI,SAAS;EACb,IAAI,eAAe;AACnB,OAAK,IAAI,IAAI,GAAG,IAAI,YAAY,KAAK;AACpC,YAAO,MAAM,+BAA+B,IAAI,EAAE,MAAM,WAAW,YAAY,SAAS;GACxF,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,aAAa,OAAO,cAAc;IACjF,QAAQ;IACR,SAAS,KAAK,SAAS;IACvB,MAAM,KAAK,UAAU;KACpB,QAAQ,WAAW,KAAK,OAAO;MAC9B,GAAG;MACH,MAAM,aAAa,EAAE,MAAM,OAAO;MAClC,QAAQ,aAAa,EAAE,QAAQ,OAAO;MACtC,gBAAgB,aAAa,EAAE,gBAAgB,OAAO;MACtD,EAAE;KACH,WAAW,aAAa;KACxB,CAAC;IACF,CAAC;AACF,kBAAe;AACf,YAAS,KAAK,MAAM,SAAS,EAAE;AAC/B,OAAI,SAAS,WAAW,IAAK;;AAE9B,MAAI,gBAAgB,CAAC,aAAa,GAAI,OAAM,KAAK,YAAY,aAAa;;;AAM5E,IAAI,2BAA2C,yBAAS,4BAA4B;AACnF,4BAA2B,eAAe;AAC1C,4BAA2B,UAAU;AACrC,QAAO;EACN,4BAA4B,EAAE,CAAC;;;;AAIjC,IAAI,qBAAqB,cAAc,aAAa;CACnD,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BlC,MAAM,MAAM,SAAS;EACpB,MAAM,EAAE,MAAM,UAAU,UAAU;EAClC,IAAI;AACJ,MAAI,aAAa,WAAW,QAAQ,SAAS;GAC5C,MAAM,mBAAmB,aAAa,QAAQ,QAAQ,GAAG,QAAQ,UAAU,kBAAkB,QAAQ,QAAQ;AAC7G,aAAU;IACT;IACA;IACA;IACA,QAAQ,yBAAyB;IACjC,SAAS;IACT;aACS,YAAY,WAAW,QAAQ,QAAQ;GACjD,MAAM,kBAAkB,aAAa,QAAQ,OAAO,GAAG,QAAQ,SAAS,iBAAiB,QAAQ,OAAO;AACxG,aAAU;IACT;IACA;IACA;IACA,QAAQ,yBAAyB;IACjC,QAAQ;IACR;QACK,OAAM,IAAI,MAAM,iDAAiD;EACxE,MAAM,WAAW,MAAM,MAAM,KAAK,cAAc,wBAAwB;GACvE,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU,QAAQ;GAC7B,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;;AAMpD,IAAI,0BAA0B,cAAc,aAAa;CACxD,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;;;;;CAMlC,MAAM,QAAQ,EAAE,WAAW,MAAM,QAAQ,UAAU;EAClD,MAAM,WAAW,MAAM,MAAM,GAAG,KAAK,YAAY,eAAe,aAAa;GAC5E,QAAQ;GACR,SAAS;IACR,GAAG,KAAK,SAAS;IACjB,UAAU;IACV;GACD,MAAM,KAAK,UAAU;IACpB;IACA;IACA,CAAC;GACF;GACA,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,0BAA0B,SAAS,OAAO,GAAG,SAAS,aAAa;AACrG,MAAI,CAAC,SAAS,KAAM,OAAM,IAAI,MAAM,mBAAmB;AACvD,SAAO;;CAER,MAAM,OAAO,EAAE,aAAa;EAC3B,MAAM,WAAW,MAAM,MAAM,GAAG,KAAK,YAAY,eAAe,aAAa;GAC5E,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;CAEnD,MAAM,UAAU,EAAE,WAAW,UAAU;EACtC,MAAM,WAAW,MAAM,MAAM,GAAG,KAAK,YAAY,eAAe,UAAU,UAAU;GACnF,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;GAChC,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;CAEnD,MAAM,eAAe,EAAE,WAAW,QAAQ;EACzC,MAAM,WAAW,MAAM,MAAM,GAAG,KAAK,YAAY,eAAe,UAAU,UAAU;GACnF,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU;IACpB,MAAM;IACN,QAAQ,iBAAiB,KAAK,OAAO;IACrC,SAAS,kBAAkB,KAAK,QAAQ;IACxC,cAAc,KAAK,eAAe,iBAAiB,KAAK,aAAa,GAAG,KAAK;IAC7E,YAAY,KAAK;IACjB,WAAW,KAAK;IAChB,MAAM,KAAK;IACX,UAAU,KAAK;IACf,CAAC;GACF,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;;;AAMpD,IAAI,cAAc,cAAc,aAAa;CAC5C,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;CAElC,MAAM,MAAM,KAAK,aAAa,EAAE,EAAE;EACjC,MAAM,WAAW,MAAM,MAAM,GAAG,KAAK,YAAY,gBAAgB;GAChE,QAAQ;GACR,SAAS,EAAE,GAAG,KAAK,SAAS,EAAE;GAC9B,MAAM,KAAK,UAAU;IACpB,OAAO;IACP;IACA,CAAC;GACF,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,UAAQ,MAAM,SAAS,MAAM,EAAE;;;;AAOjC,IAAI,eAAe,cAAc,aAAa;;CAE7C,YAAY,aAAa,eAAe;AACvC,QAAM,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkClC,MAAM,IAAI,UAAU,MAAM;EACzB,MAAM,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC,KAAK;EACrD,MAAM,mBAAmB,aAAa,SAAS,GAAG,WAAW,kBAAkB,SAAS;EACxF,MAAM,MAAM,KAAK,cAAc;EAC/B,MAAM,UAAU;GACf,WAAW;GACX,SAAS;GACT;EACD,MAAM,WAAW,MAAM,MAAM,KAAK;GACjC,QAAQ;GACR,SAAS,KAAK,SAAS;GACvB,MAAM,KAAK,UAAU,QAAQ;GAC7B,CAAC;AACF,MAAI,CAAC,SAAS,GAAI,OAAM,KAAK,YAAY,SAAS;AAClD,SAAO,SAAS,MAAM;;;AAMxB,IAAI,gBAAgB,MAAM;CACzB,YAAY,EAAE,SAAS,eAAe,SAAS,EAAE,EAAE;AAClD,WAAS;AACT,OAAK,gBAAgB,iBAAiB,QAAQ,IAAI;EAClD,MAAM,WAAW,SAAS,SAAS,MAAM,aAAa,GAAG,SAAS,QAAQ,MAAM,aAAa,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG;AAC7G,OAAK,UAAU,IAAI,WAAW,QAAQ,IAAI,gBAAgB,QAAQ,OAAO,GAAG,CAAC,QAAQ,cAAc,GAAG,IAAI,sBAAsB,GAAG;AACnI,OAAK,iBAAiB,IAAI,sBAAsB,KAAK,SAAS,KAAK,cAAc;AACjF,OAAK,YAAY,IAAI,iBAAiB,KAAK,SAAS,KAAK,cAAc;AACvE,OAAK,SAAS,IAAI,cAAc,KAAK,SAAS,KAAK,cAAc;AACjE,OAAK,cAAc,IAAI,mBAAmB,KAAK,SAAS,KAAK,cAAc;AAC3E,OAAK,mBAAmB,IAAI,wBAAwB,KAAK,SAAS,KAAK,cAAc;AACrF,OAAK,OAAO,IAAI,YAAY,KAAK,SAAS,KAAK,cAAc;AAC7D,OAAK,QAAQ,IAAI,aAAa,KAAK,SAAS,KAAK,cAAc;;CAEhE,IAAI,gBAAgB;AACnB,SAAO,KAAK;;CAEb,IAAI,WAAW;AACd,SAAO,KAAK;;CAEb,IAAI,QAAQ;AACX,SAAO,KAAK;;CAEb,IAAI,aAAa;AAChB,SAAO,KAAK;;CAEb,IAAI,kBAAkB;AACrB,SAAO,KAAK;;CAEb,IAAI,MAAM;AACT,SAAO,KAAK;;CAEb,IAAI,OAAO;AACV,SAAO,KAAK;;;;;;ACloBd,MAAM,qBAAqB;;;;AAK3B,eAAe,kBAAkB,WAAoC;AACnE,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,SAAS,KAAK,cAAc;AAElC,SAAO,OAAO,iBAAiB;GAC7B,MAAM,OAAQ,OAAO,SAAS,CAAS;AACvC,UAAO,YAAY,QAAQ,KAAK,CAAC;IACjC;AAEF,SAAO,GAAG,UAAU,QAAa;AAC/B,OAAI,IAAI,SAAS,aAEf,SAAQ,kBAAkB,YAAY,EAAE,CAAC;OAEzC,QAAO,IAAa;IAEtB;GACF;;;;;AAMJ,SAAS,UAAU,KAAyC;AAC1D,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,OAAO;AAEX,MAAI,GAAG,SAAS,UAAU;AACxB,WAAQ,MAAM,UAAU;IACxB;AAEF,MAAI,GAAG,aAAa;AAClB,OAAI;AACF,YAAQ,OAAO,KAAK,MAAM,KAAK,GAAG,EAAE,CAAC;YAC9B,KAAK;AACZ,2BAAO,IAAI,MAAM,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG,CAAC;;IAExF;AAEF,MAAI,GAAG,SAAS,OAAO;GACvB;;;;;;;;;AAUJ,eAAsB,iBACpB,YAAoB,oBACQ;CAC5B,MAAM,wBAAQ,IAAI,KAAyB;CAC3C,IAAIG,WAA0B;EAC5B,aAAa,EAAE;EACf,WAAW;EACZ;CAED,MAAM,SAAS,KAAK,cAAc,KAAK,QAAQ;AAC7C,GAAC,YAAY;AAEX,OAAI,UAAU,+BAA+B,IAAI;AACjD,OAAI,UAAU,gCAAgC,qBAAqB;AACnE,OAAI,UAAU,gCAAgC,eAAe;AAG7D,OAAI,IAAI,WAAW,WAAW;AAC5B,QAAI,UAAU,IAAI;AAClB,QAAI,KAAK;AACT;;AAIF,OAAI,IAAI,WAAW,SAAS,IAAI,QAAQ,WAAW;AACjD,QAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,QAAI,IAAI,KAAK,UAAU,EAAE,QAAQ,MAAM,CAAC,CAAC;AACzC;;AAIF,OAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,WAAW;AAClD,QAAI;KAEF,MAAM,EAAE,cAAM,UADD,MAAM,UAAU,IAAI;AAGjC,SAAI,OAAOC,WAAS,YAAY,OAAO,UAAU,UAAU;AACzD,UAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,UAAI,IAAI,KAAK,UACX,EAAE,OAAO,8DAA8D,CACxE,CAAC;AACF;;KAIF,MAAM,WAAW,GAAG,MAAM,GAAGA;KAI7B,MAAMC,WAAgC;MACpC,MAJiB,MAAM,IAAI,SAAS;MAKpC,aAAa,SAAS;MACtB,WAAW,SAAS;MACrB;AAED,SAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,SAAI,IAAI,KAAK,UAAU,SAAS,CAAC;aAC1B,KAAK;AACZ,SAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,SAAI,IAAI,KAAK,UACX,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EAAE,CAC5D,CAAC;;AAEJ;;AAIF,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IAAI,KAAK,UAAU,EAAE,OAAO,aAAa,CAAC,CAAC;MAC7C,CAAC,OAAO,UAAU;AAEpB,OAAI,CAAC,IAAI,aAAa;AACpB,QAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,QAAI,IAAI,KAAK,UAAU,EACrB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,yBACjD,CAAC,CAAC;;IAEL;GACF;CAEF,MAAM,OAAO,MAAM,kBAAkB,UAAU;AAE/C,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,SAAO,OAAO,YAAY;AACxB,WAAQ;IACN;IACA;IACA;IACA,cAAc,gBAA+B;AAC3C,gBAAW;;IAEd,CAAC;IACF;AAEF,SAAO,GAAG,SAAS,OAAO;GAC1B;;;;;AC/JJ,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;;;;;AAa9B,IAAa,YAAb,cAA+BC,oBAAa;CAW1C,YAAY,SAA2B;AACrC,SAAO;uBALuB,KAAK,KAAK;oBAEZ;AAI5B,OAAK,SAAS,QAAQ;AACtB,OAAK,YAAY,QAAQ;AACzB,OAAK,SAAS,QAAQ;AACtB,OAAK,OAAO,QAAQ;;;;;CAMtB,MAAM,mBAAkC;AACtC,MAAI,KAAK,WACP;AAGF,OAAK,kBAAkB,IAAI,iBAAiB;AAC5C,OAAK,gBAAgB,KAAK,KAAK;AAE/B,MAAI;GACF,MAAM,WAAW,MAAM,KAAK,OAAO,gBAAgB,QAAQ;IACzD,WAAW,KAAK;IAChB,QAAQ,KAAK;IACb,QAAQ,KAAK,gBAAgB;IAC7B,MAAM,KAAK;IACZ,CAAC;AAEF,QAAK,KAAK,YAAY;AACtB,QAAK,qBAAqB;AAG1B,SAAM,KAAK,eAAe,SAAS,KAAM;WAClCC,OAAY;AACnB,OAAI,MAAM,SAAS,aAEjB;AAGF,QAAK,KAAK,SAAS,MAAM;AAEzB,OAAI,CAAC,KAAK,WAER,MAAK,mBAAmB;;;;;;CAQ9B,MAAc,eAAe,MAAiD;EAC5E,MAAM,SAAS,KAAK,WAAW;EAC/B,MAAM,UAAU,IAAI,aAAa;EAGjC,MAAM,8CAAsB,EAC1B,UAAU,UAAe;AACvB,QAAK,gBAAgB,MAAM;KAE9B,CAAC;AAEF,MAAI;AACF,UAAO,MAAM;IACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAE3C,QAAI,KACF;IAIF,MAAM,QAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;AACrD,WAAO,KAAK,MAAM;;YAEZ;AACR,UAAO,aAAa;;AAItB,MAAI,CAAC,KAAK,WACR,MAAK,mBAAmB;;;;;CAO5B,AAAQ,gBAAgB,OAAkB;AACxC,MAAI,CAAC,MAAM,KACT;AAGF,MAAI;AAGF,OAAI,MAAM,UAAU,aAAa;AAC/B,SAAK,gBAAgB,KAAK,KAAK;AAC/B,SAAK,KAAK,YAAY;cACb,MAAM,UAAU,OAAO;IAEhC,MAAMC,WAA4B;KAChC,YAAY;KACZ,MAHiB,KAAK,MAAM,MAAM,KAAK;KAIxC;AACD,SAAK,KAAK,OAAO,SAAS;cACjB,MAAM,UAAU,aAAa;IAEtC,MAAMC,iBAAwC;KAC5C,YAAY;KACZ,MAHiB,KAAK,MAAM,MAAM,KAAK;KAIxC;AACD,SAAK,KAAK,aAAa,eAAe;cAC7B,MAAM,UAAU,OACzB,MAAK,KAAK,OAAO;WAEZF,OAAY;AACnB,QAAK,KAAK,yBAAS,IAAI,MAAM,mCAAmC,QAAQ,CAAC;;;;;;CAO7E,AAAQ,sBAA4B;AAClC,OAAK,oBAAoB;AAEzB,OAAK,sBAAsB,kBAAkB;AAI3C,OAH+B,KAAK,KAAK,GAAG,KAAK,gBAC1B,qBAAqB,uBAEC;AAC3C,SAAK,KAAK,oBAAoB;AAC9B,SAAK,WAAW;;KAEjB,mBAAmB;;;;;CAMxB,AAAQ,qBAA2B;AACjC,MAAI,KAAK,qBAAqB;AAC5B,iBAAc,KAAK,oBAAoB;AACvC,QAAK,sBAAsB;;;;;;CAO/B,AAAQ,oBAA0B;AAChC,MAAI,KAAK,kBAAkB,KAAK,WAC9B;AAGF,OAAK,KAAK,eAAe;AAEzB,OAAK,iBAAiB,iBAAiB;AACrC,QAAK,iBAAiB;AACtB,QAAK,WAAW;KACf,IAAK;;;;;CAMV,AAAQ,YAAkB;AACxB,OAAK,WAAW,KAAK;AACrB,OAAK,kBAAkB,CAAC,OAAM,UAAS;AACrC,QAAK,KAAK,SAAS,MAAM;IACzB;;;;;CAMJ,AAAQ,WAAW,gBAAyB,MAAY;AACtD,MAAI,KAAK,iBAAiB;AACxB,QAAK,gBAAgB,OAAO;AAC5B,QAAK,kBAAkB;;AAGzB,OAAK,oBAAoB;AAEzB,MAAI,iBAAiB,KAAK,gBAAgB;AACxC,gBAAa,KAAK,eAAe;AACjC,QAAK,iBAAiB;;;;;;CAO1B,eAAe,QAAwB,MAAoB;AACzD,OAAK,SAAS;AACd,OAAK,OAAO;AAGZ,OAAK,WAAW;;;;;CAMlB,WAAiB;AACf,OAAK,aAAa;AAClB,OAAK,WAAW,KAAK;AACrB,OAAK,KAAK,WAAW;AACrB,OAAK,oBAAoB;;;;;;;AAQ7B,SAAgB,gBAAgB,SAAsC;AACpE,QAAO,IAAI,UAAU,QAAQ;;;;;;;;AClO/B,MAAM,wBAAwB;;;;ACjB9B,SAAgB,iBAAiB,SAAiD;CAChF,MAAM,WAAW,SAAS,YAAY;CACtC,MAAM,QACJ,SAAS,SACR,QAAQ,IAAI,gBAAgB,aAAa,EAAE,MAAM,IAClD;AAEF,0BACE,EACE,OACD,8BACU;EACT;EACA,cAAc;EACf,CAAC,CACH;;;;;ACZH,MAAMG,WAAS,kBAAkB;;;;AAWjC,IAAa,oBAAb,MAA+B;;wBACiB;;;;;CAK9C,MAAM,QAAQ,SAAuC;EACnD,MAAM,EAAE,SAAS,MAAM,qBAAW;EAGlC,MAAMC,iCAA4B,SAAS,MAAM,EAC/C,OAAO;GAAC;GAAQ;GAAQ;GAAO,EAChC,CAAC;AAEF,OAAK,iBAAiB;AAEtB,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAMC,SAAc;GACpB,IAAI,WAAW;AASf,GANW,SAAS,gBAAgB;IAClC,OAAO,MAAM;IACb,WAAW;IACZ,CAAC,CAGC,GAAG,SAAS,SAAiB;AAE9B,QAAI,KAAK,WAAW,sBAAsB,CAExC,KAAI;KACF,MAAM,cAAc,KAAK,UAAU,sBAAsB,OAAO;KAChE,MAAMC,UAAyB,KAAK,MAAM,YAAY;AAEtD,aAAQ,QAAQ,MAAhB;MAEE,KAAK;AAEH,gBAAO,QAAQ,OAAO,QAAQ,QAAQ;AACtC;MAGF,KAAK;AACH,kBAAW;AACX,gBAAO,MAAM,iBAAiB,QAAQ,QAAQ;AAC9C,WAAI,QAAQ,MACV,UAAO,MAAM,QAAQ,MAAM;AAE7B;;YAEE;AACN,cAAO,MAAM,6DAA6D;AAC1E,aAAQ,IAAI,KAAK,UAAU,sBAAsB,OAAO,CAAC;;QAI3D,SAAQ,IAAI,KAAK;KAEnB;AAGF,SAAM,OAAQ,GAAG,SAAS,SAAiB;AACzC,YAAQ,OAAO,MAAM,KAAK;KAC1B;AAGF,SAAM,GAAG,SAAS,MAAqB,WAA0B;AAC/D,QAAI,KAAK,gBAAgB,QAAQ,MAAM,IACrC,MAAK,iBAAiB;AAGxB,QAAI,OACF,wBAAO,IAAI,MAAM,gCAAgC,SAAS,CAAC;aAClD,SAAS,EAClB,SAAQ,OAAO;SACV;AACL,SAAI,CAAC,SACH,UAAO,MAAM,2BAA2B,OAAO;AAEjD,4BAAO,IAAI,MAAM,2BAA2B,OAAO,CAAC;;KAEtD;AAGF,SAAM,GAAG,UAAU,UAAiB;AAClC,SAAK,iBAAiB;AACtB,2BAAO,IAAI,MAAM,2BAA2B,MAAM,UAAU,CAAC;KAC7D;AAGF,SAAM,OAAO,MAAM,KAAK,UAAUC,SAAO,GAAG,KAAK;AACjD,SAAM,OAAO,KAAK;IAClB;;;;;;CAOJ,OAAgB;AACd,MAAI,KAAK,gBAAgB;GACvB,MAAM,gBAAgB,KAAK;AAC3B,QAAK,eAAe,KAAK,UAAU;AAGnC,oBAAiB;AAEf,QAAI,iBAAiB,cAAc,aAAa,MAAM;AACpD,cAAO,KAAK,iDAAiD;AAC7D,mBAAc,KAAK,UAAU;;MAE9B,IAAK;AACR,UAAO;;AAET,SAAO;;;;;CAMT,YAAqB;AACnB,SAAO,KAAK,mBAAmB;;;;;;;;;ACjInC,MAAMC,kBAAiD;CACrD,OAAO;EACL,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,OAAO;EACL,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,QAAQ;EACN,SAAS;EACT,MAAM,EAAE;EACT;CACD,OAAO;EACL,SAAS;EACT,MAAM,CAAC,MAAM,kBAAkB;EAChC;CACF;;;;;AAMD,SAAgB,iBACd,UACA,SACe;AAEf,KAAI,SAAS,aACX,QAAO;EACL,SAAS;EACT,MAAM,CAAC,MAAM,kBAAkB;EAChC;AAIH,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,mDAAmD;CAGrE,MAAM,MAAM,KAAK,QAAQ,SAAS;AAElC,KAAI,CAAC,gBAAgB,KACnB,OAAM,IAAI,MACR,+BAA+B,IAAI,0BACV,OAAO,KAAK,gBAAgB,CAAC,KAAK,KAAK,GACjE;CAGH,MAAM,SAAS,gBAAgB;AAG/B,KAAI;EAAC;EAAO;EAAQ;EAAO;EAAQ;EAAQ;EAAQ;EAAQ;EAAO,CAAC,SAAS,IAAI,CAC9E,KAAI;EAEF,MAAM,aAAa,QAAQ,QAAQ,0CAA0C;AAC7E,SAAO;GACL,SAAS,OAAO;GAChB,MAAM,CAAC,WAAW;GACnB;UACM,OAAO;AACd,QAAM,IAAI,MACR,2HAEU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACjE;;AAIL,QAAO;;;;;AC9FT,MAAMC,WAAS,kBAAkB;AAcjC,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAGD,MAAa,kCAAkC,CAAC,GAAG,kBAAkB,MAAM;;;;;AAM3E,MAAa,2BAA2B;AAExC,MAAM,sCAAsC;AAC1C,UAAO,MACL,iOAID;AACD,SAAQ,KAAK,EAAE;;;;;;;;;;;;AAajB,MAAM,6BAA6B,OACjC,UACA,YACgC;CAChC,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;AAEJ,KAAI;EAGF,MAAM,cAAc;EACpB,MAAM,eAAe,QAAQ,QAAQ,GAAG,YAAY,gCAAgC;EACpF,MAAM,kBAAkB,QAAQ,QAAQ,GAAG,YAAY,4BAA4B;AAGnF,SAAO,QAAQ,MAAM;AACrB,SAAO,QAAQ,MAAM;AAErB,4BAA0B,QAAQ,aAAa,CAAC;EAChD,MAAM,cAAc,QAAQ,gBAAgB;AAC5C,cAAY,YAAY;AACxB,eAAa,YAAY;AACzB,0BAAwB,YAAY;AAGpC,MAAI,CAAC,2BAA2B,CAAC,aAAa,CAAC,cAAc,CAAC,uBAAuB;AACnF,YAAO,MACL,6FAED;AACD,kCAA+B;;UAE1BC,OAAY;AACnB,MAAI,MAAM,SAAS,mBACjB,gCAA+B;AAGjC,WAAO,MAAM,mDAAmD,MAAM,UAAU;AAChF,QAAM;;CAKR,IAAIC;AACJ,KAAI;AACF,mBAAiB,wBAAwB,SAAS;AAClD,WAAO,MAAM,qCAAqC,gBAAgB,KAAK,YAAY;UAC5E,OAAO;AACd,WAAO,KACL,8EACC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EACxD;;CAIH,MAAM,aAAa,MAAM,UAAU,UAAU;EAC3C,kBAAkB,QAAQ;EAC1B,sBAAsB,QAAQ;EAC/B,CAAC;AACF,YAAW;EACT,UAAU;EACV;EACD,CAAC;CAGF,MAAM,mBAAmB,sBAAsB,QAAQ,SAAS;AAGhE,KAAI,gBAAgB;AAClB,WAAO,MAAM,+BAA+B,MAAM,KAAK,eAAe,MAAM,CAAC,CAAC,KAAK,KAAK,GAAG;AAC3F,WAAO,MACL,0BAA0B,iBAAiB,KAAK,iBAC/B,iBAAiB,WAAW,GAC9C;EAGD,IAAIC,gBAAyC;AAC7C,OAAK,MAAM,CAAC,YAAY,aAAa,eAAe,SAAS,EAAE;AAC7D,YAAO,MACL,YAAY,WAAW,gBAAgB,SAAS,KAAK,kBAAkB,aACxE;AACD,OAAI,SAAS,SAAS,iBAAiB,MAAM;AAC3C,oBAAgB;AAChB,aAAO,MAAM,uBAAuB,WAAW,eAAe,SAAS,OAAO;AAC9E;;;AAIJ,MAAI,eAAe;AACjB,oBAAiB,SAAS,cAAc;AACxC,YAAO,MAAM,uCAAuC,iBAAiB,OAAO;QAE5E,UAAO,KAAK,+CAA+C,iBAAiB,OAAO;;AAIvF,QAAO;EACL,cAAc,iBAAiB;EAC/B,QAAQ,iBAAiB,UAAU,EAAE;EACtC;;;;;AAMH,MAAM,cAAc,OAClB,SACA,SACgD,IAAI,SAAS,SAAS,WAAW;CAEjF,MAAM,EAAE,mBAAU,QAAQ,gBAAgB;CAC1C,MAAM,QAAQC,QAAM,SAAS,KAAK;CAClC,IAAI,SAAS;CACb,IAAI,SAAS;AAEb,OAAM,OAAO,GAAG,SAAS,SAAiB;AACxC,YAAU,KAAK,UAAU;GACzB;AACF,OAAM,OAAO,GAAG,SAAS,SAAiB;AACxC,YAAU,KAAK,UAAU;GACzB;AAEF,OAAM,GAAG,UAAU,SAAwB;AACzC,MAAI,SAAS,EACX,SAAQ;GAAE;GAAQ;GAAQ,CAAC;MAE3B,wBAAO,IAAI,MAAM,4BAA4B,KAAK,IAAI,SAAS,CAAC;GAElE;AAEF,OAAM,GAAG,UAAU,UAAiB;AAClC,SAAO,MAAM;GACb;EACF;;;;;;;;;AAUF,MAAa,6BAA6B,WAAwB;CAEhE,MAAMC,kBAA4B,EAAE;CACpC,IAAI,cAAc;AAClB,QAAO,MAAM;EACX,MAAM,MAAM,OAAO,QAAQ,0BAA0B,YAAY;AACjE,MAAI,QAAQ,GAAI;AAChB,kBAAgB,KAAK,IAAI;AACzB,gBAAc,MAAM;;AAGtB,KAAI,gBAAgB,WAAW,EAE7B,KAAI;AACF,SAAO,KAAK,MAAM,OAAO,MAAM,CAAC;SAC1B;AACN,QAAM,IAAI,MACR,6GAED;;CAML,IAAIC,gBAAqB;AAEzB,MAAK,MAAM,OAAO,iBAAiB;EAEjC,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,OAAO,MAAM,SAAS,CAAC,MAAM;EAO9C,MAAM,cAAc,OAAO,QAAQ,MAAM,SAAS;AAClD,MAAI,gBAAgB,IAAI;GACtB,MAAM,WAAW,OAAO,MAAM,UAAU,YAAY,CAAC,MAAM;AAC3D,OAAI;AACF,oBAAgB,KAAK,MAAM,SAAS;AACpC;WACM;;AAOV,MAAI;GACF,IAAI,QAAQ;GACZ,IAAI,WAAW;GACf,IAAI,aAAa;GACjB,IAAI,YAAY;AAEhB,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;IACxC,MAAM,OAAO,SAAS;AAEtB,QAAI,YAAY;AACd,kBAAa;AACb;;AAGF,QAAI,SAAS,QAAQ,UAAU;AAC7B,kBAAa;AACb;;AAGF,QAAI,SAAS,MAAK;AAChB,gBAAW,CAAC;AACZ;;AAGF,QAAI,SAAU;AAEd,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,SAAI,cAAc,GAAI,aAAY;AAClC;eACS,SAAS,OAAO,SAAS,KAAK;AACvC;AACA,SAAI,UAAU,KAAK,cAAc,IAAI;MAEnC,MAAM,YAAY,SAAS,MAAM,GAAG,IAAI,EAAE;AAC1C,sBAAgB,KAAK,MAAM,UAAU;AACrC;;;;AAMN,OAAI,UAAU,KAAK,cAAc,GAC/B,iBAAgB,KAAK,MAAM,SAAS;UAEhC;AAEN;;;AAIJ,KAAI,kBAAkB,KACpB,OAAM,IAAI,MACR,wHAED;AAGH,QAAO;;;;;AAMT,MAAM,yBAAyB,OAC7B,kBACA,YACgC;AAChC,UAAO,MAAM,mCAAmC,mBAAmB;CACnE,MAAM,OAAO,CAAC,WAAW;AAGzB,KAAI,QAAQ,aAEV,MAAK,KAAK,YAAY,QAAQ,aAAa;KAG3C,MAAK,KAAK,UAAU,iBAAiB;AAIvC,KAAI,QAAQ,SACV,MAAK,KAAK,cAAc,QAAQ,SAAS;AAG3C,KAAI;EAGF,MAAM,WAAW,2BADF,MAAM,YAAY,QAAQ,KAAK,EACI,OAAO;AAGzD,SAAO;GACL,cAAc,SAAS;GACvB,QAAQ,SAAS,UAAU,EAAE;GAC9B;UACM,OAAO;EACd,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,WAAO,MAAM,2CAA2C,eAAe;AACvE,MAAI,aAAa,aAAa,CAAC,SAAS,oBAAoB,IAC1D,aAAa,SAAS,oBAAoB,CAC1C,UAAO,KACL,uRAGiC,iBAAiB,GACnD;AAEH,QAAM;;;;;;AAOV,MAAa,2BAA2B,OACtC,kBACA,YAMgC;AAEhC,KAAI,QAAQ,aACV,QAAO,MAAM,uBAAuB,kBAAkB,QAAQ;CAIhE,MAAM,MAAM,KAAK,QAAQ,iBAAiB;AAI1C,KAAI,iBAAiB,SAAS,IAAI,CAChC,QAAO,MAAM,2BAA2B,kBAAkB,QAAQ;AAGpE,KAAI,QAAQ,MACV,QAAO,MAAM,uBAAuB,kBAAkB,QAAQ;AAIhE,UAAO,KAAK,uCAAuC,IAAI,QAAQ;AAC/D,QAAO;EACL,cAAc,QAAQ,YAAY,KAAK,SAAS,kBAAkB,IAAI;EACtE,QAAQ,EAAE;EACX;;;;;ACzXH,MAAM,SAAS,kBAAkB;AAgBjC,SAAS,UAAkB;AACzB,KACE,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,WAE7B,QAAO,OAAO,YAAY;AAE5B,sBAAe;;AAGjB,SAAS,eAAe,SAAkB,cAA+B;CACvE,IAAI,MAAM,WAAW;AACrB,KAAI,QAAQ,sBACV,OAAM;AAER,OAAM,IAAI,QAAQ,OAAO,GAAG;AAE5B,KAAI,yBAAyB,KAAK,IAAI,EAAE;EACtC,MAAM,OAAO,gBAAgB,IAAI,MAAM,aAAa,GAAG,IAAI,MAAM,EAAE,IAAI;AACvE,QAAM,IAAI,QAAQ,cAAc,GAAG;AACnC,SAAO,GAAG,IAAI,GAAG;;AAGnB,QAAO;;;;;AAMT,MAAM,eAAe,QAAiB;AACpC,KAAI,OAAO,QAAQ,SACjB,KAAI;AAEF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;;AAGX,QAAO;;;;;AAMT,MAAM,iBAAiB,OACrB,OACA,WACA,kBACA,QACA,iBACA,OACA,aACA,SACA,sBACkB;AAClB,QAAO,MAAM,qBAAqB;CAElC,MAAM,EAAE,UAAU,eAAe,MAAM,SAAS,cAAc,MAAM;CAEpE,MAAM,aAAa,MAAM,QAAQ,QAAQ,GACrC,QAAQ,IAAI,YAAY,GACvB,OAAO,YACR,OAAO,QAAQ,QAAQ,CAAC,KAAK,CAAC,KAAK,WAAW,CAC5C,KACA,YAAY,MAAM,CACnB,CAAC,CACH;AAEH,OAAM,OAAO;AACb,aAAY;EACV,aAAa,EAAE;EACJ;EACZ,CAAC;AAEF,KAAI;AAEF,MAAI,CAAC,YAAY,SAAS,MAAM,KAAK,GACnC,QAAO,KAAK,oCAAoC;OAC3C;GAEL,MAAM,QAAQ,OAAO,KAAK,iBAAiB,EAAE,CAAC;AAC9C,OAAI,MAAM,WAAW,EACnB,QAAO,KAAK,oCAAoC;QAC3C;IACL,MAAM,QAAQ;;;;;;;AAQd,WAAO,MAAM,6BAA6B,SAAS,KAAK;IACxD,MAAM,QAAQ,MAAM,OAAO,IAAI,MAAM,OAAO;KAC1C,SAAS;KACF;KACR,CAAC;AACF,WAAO,MAAM,YAAY,MAAM,OAAO,qBAAqB;IAG3D,MAAMC,cAAqC,EAAE;AAC7C,SAAK,MAAM,QAAQ,OAAO;KACxB,MAAMC,SAAO,KAAK;AAClB,SAAI,CAAC,YAAYA,QACf,aAAYA,UAAQ,EAAE;AAExB,iBAAYA,QAAM,KAAK,KAAK;;AAG9B,SAAK,MAAM,CAACA,QAAM,cAAc,OAAO,QAAQ,YAAY,EAAE;KAC3D,MAAM,WAAW,gBAAgBA,WAAS;KAC1C,MAAM,eAAe,UAAU,MAAM,GAAG,SAAS;AAEjD,kBAAa,SAAS,MAAM,UAAU;MAEpC,IAAI;MACJ,IAAI;MACJ,IAAI;AAEJ,UAAI;AACF,qBACE,OAAO,KAAK,UAAU,WAClB,KAAK,MAAM,KAAK,MAAM,GACtB,KAAK;cACL;AACN,qBAAc,KAAK;;AAGrB,UAAI;AACF,sBACE,OAAO,KAAK,WAAW,WACnB,KAAK,SACL,KAAK,UAAU,KAAK,OAAO;cAC3B;AACN,sBAAe,OAAO,KAAK,OAAO;;AAGpC,UAAI;AACF,0BACE,OAAO,KAAK,eAAe,WACvB,KAAK,MAAM,KAAK,WAAW,GAC3B,KAAK;cACL;AACN,0BAAmB,EAAE;;MAGvB,MAAMC,aAAyB;OAC7B,MAAM,KAAK;OACX,OAAO;OACP,QAAQ;OACR,YAAY;OACb;MAED,MAAM,WAAW,GAAG,MAAM,GAAGD;AAC7B,YAAM,IAAI,UAAU,WAAW;OAC/B;AAEF,YAAO,KAAK,UAAU,aAAa,OAAO,mBAAmBA,SAAO;;AAItE,gBAAY;KACV,aAAa,iBAAiB,EAAE;KAChC;KACD,CAAC;;;EAKN,MAAM,UACJ,QAAQ,WAAW,QAAQ,IAAI,iBAAiB;EAClD,MAAM,WACJ,QAAQ,SACP,QAAQ,MAAM,aAAa,GACxB,SAAS,QAAQ,MAAM,aAAa,CAAE,GAAG,MAAM,EAAE,CAAC,GAClD;EACN,MAAM,WAAW,QAAQ,YAAY;EAGrC,MAAME,MAA8B;GAClC,yBAAyB;GACzB,mCAAmC,oBAAoB;GACxD;EAGD,MAAMC,eAA6B;GACjC,UAAU,QAAQ,eAAe,SAAY;GAC7C,YAAY,QAAQ;GACpB,cAAc,QAAQ;GACtB,MAAM;GACN;GACA;GACA;GACA,eAAe,QAAQ;GACvB;GACA;GACA,kBAAkB,QAAQ;GAC1B,sBAAsB,QAAQ;GAC/B;EAGD,MAAM,gBAAgB,QAAQ,UAC1B;GAAE,SAAS,QAAQ;GAAS,MAAM,QAAQ,eAAe,EAAE;GAAE,GAC7D,iBACA,QAAQ,eAAe,SAAY,kBACnC,QACD;AAEH,MAAI;AACF,SAAM,OAAO,gBAAgB,UAAU;IACrC;IACA,QAAQ;IACT,CAAC;WACKC,OAAY;AACnB,UAAO,MACL,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,QACpF;;AAIH,QAAM,kBAAkB,QAAQ;GAC9B,SAAS,cAAc;GACvB,MAAM,cAAc;GACpB,QAAQ;GACT,CAAC;AAEF,MAAI;AACF,SAAM,OAAO,gBAAgB,UAAU;IACrC;IACA,QAAQ;IACT,CAAC;WACKA,OAAY;AACnB,UAAO,MACL,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,QACpF;;UAEIA,OAAY;AACnB,SAAO,MACL,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,QACvE;AACD,MAAI,iBAAiB,SAAS,MAAM,MAClC,QAAO,MAAM,MAAM,MAAM;AAE3B,MAAI;AACF,SAAM,OAAO,gBAAgB,UAAU;IACrC;IACA,QAAQ;IACT,CAAC;WACKA,SAAY;AACnB,UAAO,MACL,0CAA0CC,mBAAiB,QAAQA,QAAM,UAAUA,UACpF;;;;;;;AAQP,eAAsB,OACpB,UACA,UAAsB,EAAE,EACT;CAEf,MAAM,iBAAiB,CAAC,CAAC,QAAQ;CACjC,MAAM,mBAAmB,YAAY,QAAQ;CAC7C,IAAI,kBAAkB;CAGtB,MAAM,YAAY,SAAS;CAG3B,MAAM,SAAS,IAAI,cAAc;EAC/B,SAAS,QAAQ;EACjB,eAAe,QAAQ;EACvB,MAAM,QAAQ;EACf,CAAC;AAGF,QAAO,MAAM,2BAA2B;CACxC,MAAM,EACJ,MAAM,iBACN,QAAQ,aACR,OACA,gBACE,MAAM,kBAAkB;AAC5B,QAAO,MAAM,gCAAgC,kBAAkB;CAG/D,MAAM,oBAAoB,IAAI,mBAAmB;CAGjD,IAAI,eAAe,QAAQ;CAC3B,IAAIC,SAAyB,EAAE;AAE/B,KAAI;AAOF,MAJE,kBACC,YACC,gCAAgC,SAAS,KAAK,QAAQ,SAAS,CAAC,EAEhD;AAClB,UAAO,MAAM,sCAAsC;GACnD,MAAM,WAAW,MAAM,yBACrB,kBACA,QACD;AACD,kBAAe,SAAS;AACxB,YAAS,SAAS;AAElB,UAAO,KAAK,qBAAqB,eAAe;AAChD,UAAO,MAAM,wBAAwB,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG;aAC9D,UAAU;AAEnB,kBACE,QAAQ,YAAY,KAAK,SAAS,UAAU,KAAK,QAAQ,SAAS,CAAC;AACrE,UAAO,KACL,wCAAwC,KAAK,QAAQ,SAAS,CAAC,QAChE;;UAEI,OAAO;AACd,SAAO,MACL,+CACG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAC1D;AACD,cAAY,OAAO;AACnB,QAAM;;AAIR,QAAO,MAAM,6BAA6B;CAC1C,MAAM,UAAU,iBAAS,MAAM,KAAK;EAClC,UAAU,WAAiB;GACzB,MAAM,cAAc;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;AAGD,OADqBN,OAAK,MAAM,QAAQ,CACvB,MAAM,YAAY,YAAY,SAAS,QAAQ,CAAC,CAC/D,QAAO;AAGT,OAAIA,OAAK,SAAS,OAAO,IAAIA,OAAK,SAAS,OAAO,CAChD,QAAO;AAGT,UAAO;;EAET,YAAY;EACZ,eAAe;EACf,kBAAkB;GAChB,oBAAoB;GACpB,cAAc;GACf;EACF,CAAC;AAGF,QAAO,MAAM,2BAA2B;CACxC,IAAIO,YAA8B;AAElC,KAAI;AACF,cAAY,gBAAgB;GAC1B;GACA;GACQ;GACR,MAAM,gBAAgB;GACvB,CAAC;EAIF,IAAIC,oBAA0C;EAE9C,IAAI,gBAAgB;AAGpB,YAAU,GAAG,mBAAmB;AAC9B,UAAO,MAAM,qBAAqB;IAClC;AAEF,YAAU,GAAG,QAAQ,UAA2B;AAE9C,OAAI,sBAAsB,MAAM;AAC9B,WAAO,KAAK,mDAAmD;AAC/D;;AAIF,wBAAqB,YAAY;AAC/B,QAAI;AAEF,qBAAgB;AAGhB,SAAI,iBAAiB;AACnB,aAAO,KAAK,4CAA4C;AAIxD,UACE,kBACC,YACC,gCAAgC,SAC9B,KAAK,QAAQ,SAAS,CACvB,CAEH,KAAI;OACF,MAAM,WAAW,MAAM,yBACrB,kBACA,QACD;AAGD,WAAI,eAAe;AACjB,eAAO,KAAK,0CAA0C;AACtD;;AAGF,cAAO,MACL,8BAA8B,SAAS,eACxC;AACD,cAAO,MACL,uBAAuB,KAAK,UAAU,SAAS,QAAQ,MAAM,EAAE,GAChE;AAGD,WAAI,WAAW;AACb,kBAAU,eACR,SAAS,QACT,SAAS,aACV;AACD,eAAO,MAAM,uCAAuC;;AAEtD,yBAAkB;eACXJ,OAAY;AACnB,cAAO,MACL,0CACG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAC1D;AACD,WAAI,iBAAiB,SAAS,MAAM,MAClC,QAAO,MAAM,gBAAgB,MAAM,QAAQ;AAI7C;;UAIF,mBAAkB;;AAKtB,SAAI,eAAe;AACjB,aAAO,KAAK,iCAAiC;AAC7C;;AAIF,WAAM,eACJ,OACA,WACA,kBACA,QACA,iBACA,OACA,aACA,SACA,kBACD;aACM,OAAO;AACd,YAAO,MACL,4CACG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAC1D;cACO;AAER,yBAAoB;;OAEpB;IACJ;AAEF,YAAU,GAAG,cAAc,UAAiC;GAC1D,MAAM,YAAY,MAAM,KAAK;GAC7B,MAAMK,cAAY,MAAM,KAAK;GAC7B,MAAM,cAAc,eAAe,QAAQ,SAAS,QAAQ,aAAa;AACzE,OAAI,CAAC,gBACH,QAAO,KACL,wBAAwB,YAAY,WAAW,UAAU,qBAAqBA,cAC/E;AAEH,qBAAkB;IAClB;AAEF,YAAU,GAAG,UAAU,UAAiB;AACtC,UAAO,KAAK,gCAAgC,MAAM,UAAU;IAC5D;AAEF,YAAU,GAAG,sBAAsB;AACjC,UAAO,KAAK,6BAA6B;IACzC;AAEF,YAAU,GAAG,2BAA2B;AACtC,UAAO,MAAM,qCAAqC;IAClD;AAEF,YAAU,GAAG,cAAc;AACzB,UAAO,MAAM,sBAAsB;AAEnC,mBAAgB;AAKhB,OAHkB,kBAAkB,MAAM,CAIxC,QAAO,KAAK,wBAAwB;IAEtC;EAGF,IAAIC,gBAAuC;EAC3C,IAAI,kBAAkB;AACtB,UAAQ,GAAG,WAAW,gBAAwB;AAC5C,UAAO,KAAK,iBAAiB,YAAY,wBAAwB;AAGjE,OAAI,cACF,cAAa,cAAc;AAI7B,mBAAgB,iBAAiB;AAC/B,WAAO,MAAM,8CAA8C;AAC3D,oBAAgB;AAChB,sBAAkB;MACjB,IAAI;IACP;EAGF,MAAM,iBAAiB;AACrB,UAAO,MAAM,mBAAmB;AAGhC,OAAI,eAAe;AACjB,iBAAa,cAAc;AAC3B,oBAAgB;;AAElB,qBAAkB;AAGlB,UAAO,MAAM,0BAA0B;AACvC,WAAQ,OAAO,CAAC,OAAO,UAAe;AACpC,WAAO,MACL,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,QAC3E;KACD;AAGF,qBAAkB,MAAM;AAGxB,UAAO,MAAM,+BAA+B;AAC5C,UAAO,gBACJ,OAAO,EAAE,WAAW,CAAC,CACrB,WAAW;AACV,QAAI,UACF,WAAU,UAAU;AAGtB,gBAAY,YAAY;AACtB,YAAO,MAAM,sBAAsB;MACnC;AACF,YAAQ,KAAK,EAAE;KACf,CACD,OAAO,UAAe;AACrB,WAAO,KACL,sCAAsC,iBAAiB,QAAQ,MAAM,UAAU,QAChF;AACD,YAAQ,KAAK,EAAE;KACf;;AAGN,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAG/B,UAAQ,MAAM,QAAQ;AAGtB,SAAO,MAAM,2BAA2B;AACxC,QAAM,UAAU,kBAAkB;UAC3B,OAAO;AACd,SAAO,MACL,mCACG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAC1D;AAGD,MAAI;AACF,SAAM,OAAO,gBAAgB,OAAO,EAAE,WAAW,CAAC;UAC5C;AAIR,QAAM,QAAQ,OAAO;AACrB,cAAY,YAAY;AACtB,WAAQ,KAAK,EAAE;IACf;;;;;;AChpBN,eAAe,OAAO;CACpB,MAAM,UAAU,IAAIC,mBAAS;AAE7B,SACG,KAAK,WAAW,CAChB,YAAY,iCAAiC,CAC7C,QAAQC,WAAS,iBAAiB,yBAAyB;AAE9D,SACG,QAAQ,MAAM,CACd,YAAY,4BAA4B,CACxC,SACC,UACA,8FACD,CACA,OACC,gCACA,iFACD,CACA,OACC,qBACA,sEACD,CACA,OACC,2BACA,iFACD,CACA,OACC,oBACA,8FACD,CACA,OAAO,iBAAiB,8CAA8C,QACrE,SAAS,KAAK,GAAG,CAClB,CACA,OACC,sBACA,wDACC,QAAQ,SAAS,KAAK,GAAG,CAC3B,CACA,OACC,0BACA,oDACC,QAAQ,SAAS,KAAK,GAAG,CAC3B,CACA,OACC,qCACA,uNAGD,CACA,OACC,0CACA,uPAGD,CACA,OACC,uBACA,oEACD,CACA,OACC,4BACA,8CACD,CACA,OAAO,OAAO,MAA0B,YAAY;AAEnD,MAAI,CAAC,QAAQ,CAAC,QAAQ,cAAc;AAClC,WAAQ,MAAM,sEAAsE;AACpF,WAAQ,KAAK,EAAE;;AAEjB,MAAI,QAAQ,QAAQ,cAAc;AAChC,WAAQ,MAAM,qEAAqE;AACnF,WAAQ,KAAK,EAAE;;AAGjB,QAAM,OAAO,MAAM,QAAQ;GAC3B,CACD,YACC,SACA;;;;;;EAOD;AAEH,OAAM,QAAQ,YAAY;;AAG5B,MAAM,CAAC,OAAO,QAAQ;AACpB,SAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,IAAI;AACvD,SAAQ,KAAK,EAAE;EACf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lmnr-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "CLI for Laminar AI rollout debugging",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "laminar",
18
18
  "lmnr",
19
19
  "cli",
20
- "rollout"
20
+ "debugger"
21
21
  ],
22
22
  "author": "founders@lmnr.ai",
23
23
  "license": "Apache-2.0",
@@ -30,8 +30,8 @@
30
30
  "uuid": "^13.0.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@lmnr-ai/client": "0.8.7",
34
- "@lmnr-ai/types": "0.8.7"
33
+ "@lmnr-ai/types": "0.8.13",
34
+ "@lmnr-ai/client": "0.8.13"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@lmnr-ai/lmnr": "*"