lmnr-cli 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +88 -24
- package/dist/index.cjs.map +1 -1
- package/package.json +8 -7
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,8 @@ csv_parser = __toESM(csv_parser);
|
|
|
40
40
|
let export_to_csv = require("export-to-csv");
|
|
41
41
|
let fs_promises = require("fs/promises");
|
|
42
42
|
fs_promises = __toESM(fs_promises);
|
|
43
|
+
let cli_table3 = require("cli-table3");
|
|
44
|
+
cli_table3 = __toESM(cli_table3);
|
|
43
45
|
let chokidar = require("chokidar");
|
|
44
46
|
chokidar = __toESM(chokidar);
|
|
45
47
|
let http = require("http");
|
|
@@ -51,7 +53,7 @@ let readline = require("readline");
|
|
|
51
53
|
readline = __toESM(readline);
|
|
52
54
|
|
|
53
55
|
//#region package.json
|
|
54
|
-
var version$1 = "0.1.
|
|
56
|
+
var version$1 = "0.1.8";
|
|
55
57
|
|
|
56
58
|
//#endregion
|
|
57
59
|
//#region ../../node_modules/.pnpm/dotenv@17.2.3/node_modules/dotenv/package.json
|
|
@@ -1231,6 +1233,68 @@ function outputJsonError(error, exitCode = 1) {
|
|
|
1231
1233
|
process.exit(exitCode);
|
|
1232
1234
|
}
|
|
1233
1235
|
|
|
1236
|
+
//#endregion
|
|
1237
|
+
//#region src/utils/table.ts
|
|
1238
|
+
const DEFAULT_TERMINAL_WIDTH = 80;
|
|
1239
|
+
const PADDING_RIGHT = 2;
|
|
1240
|
+
const noBorderChars = {
|
|
1241
|
+
top: "",
|
|
1242
|
+
"top-mid": "",
|
|
1243
|
+
"top-left": "",
|
|
1244
|
+
"top-right": "",
|
|
1245
|
+
bottom: "",
|
|
1246
|
+
"bottom-mid": "",
|
|
1247
|
+
"bottom-left": "",
|
|
1248
|
+
"bottom-right": "",
|
|
1249
|
+
left: "",
|
|
1250
|
+
"left-mid": "",
|
|
1251
|
+
mid: "",
|
|
1252
|
+
"mid-mid": "",
|
|
1253
|
+
right: "",
|
|
1254
|
+
"right-mid": "",
|
|
1255
|
+
middle: ""
|
|
1256
|
+
};
|
|
1257
|
+
function getTerminalWidth() {
|
|
1258
|
+
return process.stdout.columns || DEFAULT_TERMINAL_WIDTH;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Calculate column widths that fit within the terminal width.
|
|
1262
|
+
* Distributes available space proportionally based on content width.
|
|
1263
|
+
*/
|
|
1264
|
+
function fitColumnWidths(contentWidths, terminalWidth) {
|
|
1265
|
+
const overhead = contentWidths.length * PADDING_RIGHT;
|
|
1266
|
+
const totalContentWidth = contentWidths.reduce((sum, w) => sum + w, 0);
|
|
1267
|
+
if (totalContentWidth + overhead <= terminalWidth) return;
|
|
1268
|
+
const availableContent = terminalWidth - overhead;
|
|
1269
|
+
const minColWidth = 5;
|
|
1270
|
+
return contentWidths.map((w) => Math.max(minColWidth + PADDING_RIGHT, Math.floor(w / totalContentWidth * availableContent) + PADDING_RIGHT));
|
|
1271
|
+
}
|
|
1272
|
+
function truncate(str, maxLen) {
|
|
1273
|
+
if (maxLen < 1) return str;
|
|
1274
|
+
if (str.length <= maxLen) return str;
|
|
1275
|
+
return str.slice(0, maxLen - 1) + "…";
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Render a borderless table from column headers and row data.
|
|
1279
|
+
* Automatically truncates content when the table exceeds terminal width.
|
|
1280
|
+
*/
|
|
1281
|
+
function renderTable(head, rows) {
|
|
1282
|
+
const terminalWidth = getTerminalWidth();
|
|
1283
|
+
const colWidths = fitColumnWidths(head.map((h, i) => rows.reduce((max, row) => Math.max(max, (row[i] ?? "").length), h.length)), terminalWidth);
|
|
1284
|
+
const table = new cli_table3.default({
|
|
1285
|
+
head: colWidths ? head.map((h, i) => truncate(h, colWidths[i] - PADDING_RIGHT)) : head,
|
|
1286
|
+
chars: noBorderChars,
|
|
1287
|
+
style: {
|
|
1288
|
+
"padding-left": 0,
|
|
1289
|
+
"padding-right": PADDING_RIGHT
|
|
1290
|
+
},
|
|
1291
|
+
...colWidths && { colWidths }
|
|
1292
|
+
});
|
|
1293
|
+
if (colWidths) for (const row of rows) table.push(row.map((cell, i) => truncate(cell, colWidths[i] - PADDING_RIGHT)));
|
|
1294
|
+
else for (const row of rows) table.push(row);
|
|
1295
|
+
return table.toString();
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1234
1298
|
//#endregion
|
|
1235
1299
|
//#region src/commands/dataset/index.ts
|
|
1236
1300
|
const logger$4 = initializeLogger();
|
|
@@ -1278,14 +1342,19 @@ const handleDatasetsList = async (options) => {
|
|
|
1278
1342
|
console.log("No datasets found.");
|
|
1279
1343
|
return;
|
|
1280
1344
|
}
|
|
1281
|
-
const
|
|
1282
|
-
const createdAtWidth = 19;
|
|
1283
|
-
console.log(`\n${"ID".padEnd(idWidth)} ${"Created At".padEnd(createdAtWidth)} Name`);
|
|
1284
|
-
console.log(`${"-".repeat(idWidth)} ${"-".repeat(createdAtWidth)} ${"-".repeat(20)}`);
|
|
1285
|
-
for (const dataset of datasets) {
|
|
1345
|
+
const rows = datasets.map((dataset) => {
|
|
1286
1346
|
const createdAtStr = new Date(dataset.createdAt).toISOString().replace("T", " ").substring(0, 19);
|
|
1287
|
-
|
|
1288
|
-
|
|
1347
|
+
return [
|
|
1348
|
+
dataset.id,
|
|
1349
|
+
createdAtStr,
|
|
1350
|
+
dataset.name
|
|
1351
|
+
];
|
|
1352
|
+
});
|
|
1353
|
+
console.log(renderTable([
|
|
1354
|
+
"ID",
|
|
1355
|
+
"Created At",
|
|
1356
|
+
"Name"
|
|
1357
|
+
], rows));
|
|
1289
1358
|
console.log(`\nTotal: ${datasets.length} dataset(s)\n`);
|
|
1290
1359
|
} catch (error) {
|
|
1291
1360
|
if (options.json) outputJsonError(error);
|
|
@@ -2497,12 +2566,8 @@ const handleSqlQuery = async (query, options) => {
|
|
|
2497
2566
|
return;
|
|
2498
2567
|
}
|
|
2499
2568
|
const columns = Object.keys(rows[0]);
|
|
2500
|
-
const
|
|
2501
|
-
|
|
2502
|
-
const divider = widths.map((w) => "-".repeat(w)).join(" ");
|
|
2503
|
-
console.log(`\n${header}`);
|
|
2504
|
-
console.log(divider);
|
|
2505
|
-
for (const row of rows) console.log(columns.map((col, i) => String(row[col] ?? "").padEnd(widths[i])).join(" "));
|
|
2569
|
+
const tableRows = rows.map((row) => columns.map((col) => String(row[col] ?? "")));
|
|
2570
|
+
console.log(renderTable(columns, tableRows));
|
|
2506
2571
|
console.log(`\n${rows.length} row(s)\n`);
|
|
2507
2572
|
} catch (error) {
|
|
2508
2573
|
if (options.json) outputJsonError(error);
|
|
@@ -2607,16 +2672,15 @@ Examples:
|
|
|
2607
2672
|
});
|
|
2608
2673
|
program.addHelpText("after", `
|
|
2609
2674
|
Examples:
|
|
2610
|
-
lmnr-cli dev agent.ts
|
|
2611
|
-
lmnr-cli dev agent.py
|
|
2612
|
-
lmnr-cli dev -m src.agent
|
|
2613
|
-
lmnr-cli dataset list --json
|
|
2614
|
-
lmnr-cli dataset push data.jsonl -n my-dataset --json
|
|
2615
|
-
lmnr-cli dataset pull output.jsonl -n my-dataset --json
|
|
2616
|
-
lmnr-cli sql query "SELECT * FROM spans LIMIT 10" --json
|
|
2617
|
-
lmnr-cli sql query "SELECT t.id, s.name FROM traces t
|
|
2618
|
-
|
|
2619
|
-
lmnr-cli sql schema # Show available tables
|
|
2675
|
+
lmnr-cli dev agent.ts # Debugger TypeScript entrypoint
|
|
2676
|
+
lmnr-cli dev agent.py # Debugger Python script mode
|
|
2677
|
+
lmnr-cli dev -m src.agent # Debugger Python module mode
|
|
2678
|
+
lmnr-cli dataset list --json # List all datasets
|
|
2679
|
+
lmnr-cli dataset push data.jsonl -n my-dataset --json # Push data to a dataset
|
|
2680
|
+
lmnr-cli dataset pull output.jsonl -n my-dataset --json # Pull data from a dataset
|
|
2681
|
+
lmnr-cli sql query "SELECT * FROM spans LIMIT 10" --json # Query spans
|
|
2682
|
+
lmnr-cli sql query "SELECT t.id, s.name FROM traces t JOIN spans s ON t.id = s.trace_id" --json
|
|
2683
|
+
lmnr-cli sql schema # Show available tables
|
|
2620
2684
|
`);
|
|
2621
2685
|
await program.parseAsync();
|
|
2622
2686
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["fs","path","crypto","initializeLogger","logger$2","newUUID","logger$1","DEFAULT_DATASET_PUSH_BATCH_SIZE","logger","logger","collectedFiles: string[]","fs","parsed: any","results: any[]","result: Datapoint<D, T>[]","logger","result: Datapoint<D, T>[]","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","logger","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/utils/logger.ts","../src/utils/file.ts","../src/utils/output.ts","../src/commands/dataset/index.ts","../src/cache-server.ts","../src/sse-client.ts","../../types/dist/index.mjs","../src/subprocess/executor.ts","../src/worker-registry.ts","../src/commands/dev/metadata.ts","../src/commands/dev/index.ts","../src/commands/sql/index.ts","../src/commands/sql/schema.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.15\";\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 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 destination: 2,\n }),\n );\n}\n","import { Datapoint } from '@lmnr-ai/types';\nimport csv from 'csv-parser';\nimport { asString, generateCsv, mkConfig } from 'export-to-csv';\nimport { createReadStream } from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nimport { initializeLogger } from './logger';\n\nconst logger = initializeLogger();\n\n/**\n * Check if a file has a supported extension.\n */\nconst isSupportedFile = (file: string): boolean => {\n const ext = path.extname(file).toLowerCase();\n return ['.json', '.csv', '.jsonl'].includes(ext);\n};\n\n/**\n * Collect all supported files from the given paths.\n * Handles both files and directories.\n */\nexport const collectFiles = async (\n paths: string[],\n recursive: boolean = false,\n): Promise<string[]> => {\n const collectedFiles: string[] = [];\n\n for (const filepath of paths) {\n try {\n const stats = await fs.stat(filepath);\n\n if (stats.isFile()) {\n if (isSupportedFile(filepath)) {\n collectedFiles.push(filepath);\n } else {\n logger.warn(`Skipping unsupported file type: ${filepath}`);\n }\n } else if (stats.isDirectory()) {\n const entries = await fs.readdir(filepath);\n\n for (const entry of entries) {\n const fullPath = path.join(filepath, entry);\n const entryStats = await fs.stat(fullPath);\n\n if (entryStats.isFile() && isSupportedFile(fullPath)) {\n collectedFiles.push(fullPath);\n } else if (recursive && entryStats.isDirectory()) {\n const subFiles = await collectFiles([fullPath], true);\n collectedFiles.push(...subFiles);\n }\n }\n }\n } catch (error) {\n logger.warn(\n `Path does not exist or is not accessible: ${filepath}. `\n + `Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return collectedFiles;\n};\n\n/**\n * Read a JSON file and return its contents.\n */\nconst readJsonFile = async (filepath: string): Promise<any[]> => {\n const content = await fs.readFile(filepath, 'utf-8');\n const parsed = JSON.parse(content);\n return Array.isArray(parsed) ? parsed : [parsed];\n};\n\n/**\n * Try to parse a string as JSON. If it fails, return the original string.\n */\nconst tryParseJson = (content: string): any => {\n // Don't try to parse if it's not a string or doesn't look like JSON\n if (typeof content !== 'string') {\n return content;\n }\n\n // If it doesn't start with { or [, it's probably not JSON\n const trimmed = content.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return content;\n }\n\n try {\n return JSON.parse(content);\n } catch (error) {\n logger.debug(\n `Error parsing JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n return content;\n }\n};\n\n/**\n * Parse each field in a CSV row, attempting to convert JSON strings back to objects.\n */\nconst parseCsvRow = (row: Record<string, string>): any => {\n const parsed: any = {};\n for (const [key, value] of Object.entries(row)) {\n parsed[key] = tryParseJson(value);\n }\n return parsed;\n};\n\n/**\n * Read a CSV file and return its contents as an array of objects.\n */\nconst readCsvFile = async (filepath: string): Promise<any[]> => new Promise((resolve, reject) => {\n const results: any[] = [];\n createReadStream(filepath)\n .pipe(csv())\n .on('data', (data) => results.push(parseCsvRow(data)))\n .on('end', () => resolve(results))\n .on('error', reject);\n});\n\n/**\n * Read a JSONL file and return its contents as an array of objects.\n */\nasync function readJsonlFile(filepath: string): Promise<any[]> {\n const content = await fs.readFile(filepath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim());\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return lines.map((line) => JSON.parse(line));\n}\n\n/**\n * Read a single file and return its contents.\n */\nasync function readFile(filepath: string): Promise<any[]> {\n const ext = path.extname(filepath).toLowerCase();\n\n if (ext === '.json') {\n return readJsonFile(filepath);\n } else if (ext === '.csv') {\n return readCsvFile(filepath);\n } else if (ext === '.jsonl') {\n return readJsonlFile(filepath);\n } else {\n throw new Error(`Unsupported file type: ${ext}`);\n }\n}\n\n/**\n * Load data from all files in the specified paths.\n */\nexport const loadFromPaths = async <D = any, T = any>(\n paths: string[],\n recursive: boolean = false,\n): Promise<Datapoint<D, T>[]> => {\n const files = await collectFiles(paths, recursive);\n\n if (files.length === 0) {\n logger.warn('No supported files found in the specified paths');\n return [];\n }\n\n logger.info(`Found ${files.length} file(s) to read`);\n\n const result: Datapoint<D, T>[] = [];\n\n for (const file of files) {\n try {\n const data = await readFile(file);\n result.push(...data);\n logger.info(`Read ${data.length} record(s) from ${file}`);\n } catch (error) {\n logger.error(\n `Error reading file ${file}: ${error instanceof Error ? error.message : String(error)}`,\n );\n throw error;\n }\n }\n\n return result;\n};\n\n/**\n * Write data to a JSON file.\n */\nconst writeJsonFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n const content = JSON.stringify(data, null, 2);\n await fs.writeFile(filepath, content, 'utf-8');\n};\n\n/**\n * Format data as a CSV string.\n */\nconst formatCsv = <D, T>(data: Datapoint<D, T>[]): string => {\n const formattedData = data.map(item =>\n Object.fromEntries(Object.entries(item).map(([key, value]) => [key, stringifyForCsv(value)]),\n ));\n\n const csvConfig = mkConfig({ useKeysAsHeaders: true });\n const csvOutput = generateCsv(csvConfig)(formattedData);\n return asString(csvOutput);\n};\n\n/**\n * Write data to a CSV file.\n */\nconst writeCsvFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n if (data.length === 0) {\n throw new Error('No data to write to CSV');\n }\n\n await fs.writeFile(filepath, formatCsv(data), 'utf-8');\n};\n\n/**\n * Write data to a JSONL file.\n */\nconst writeJsonlFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n const lines = data.map((item) => JSON.stringify(item)).join('\\n');\n await fs.writeFile(filepath, lines + '\\n', 'utf-8');\n};\n\n/**\n * Write data to a file based on the file extension.\n */\nexport const writeToFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n format?: 'json' | 'csv' | 'jsonl',\n): Promise<void> => {\n // Create parent directories if they don't exist\n const dir = path.dirname(filepath);\n await fs.mkdir(dir, { recursive: true });\n\n // Determine the format\n const ext = format ?? path.extname(filepath).slice(1);\n\n if (format && format !== path.extname(filepath).slice(1)) {\n logger.warn(\n `Output format ${format} does not match file extension ${path.extname(filepath).slice(1)}`,\n );\n }\n\n if (ext === 'json') {\n await writeJsonFile(filepath, data);\n } else if (ext === 'csv') {\n await writeCsvFile(filepath, data);\n } else if (ext === 'jsonl') {\n await writeJsonlFile(filepath, data);\n } else {\n throw new Error(`Unsupported output format: ${ext}`);\n }\n};\n\n/**\n * Convert a value to a CSV-safe string.\n * - Strings and numbers pass through\n * - null/undefined become empty strings\n * - Objects and arrays are stringified to JSON\n */\nconst stringifyForCsv = (value: any): string => {\n if (value === null || value === undefined) {\n return '';\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n // For objects and arrays, stringify to JSON\n return JSON.stringify(value);\n};\n\n/**\n * Print data to console in the specified format.\n */\nexport const printToConsole = <D, T>(\n data: Datapoint<D, T>[],\n format: 'json' | 'csv' | 'jsonl' = 'json',\n) => {\n if (format === 'json') {\n console.log(JSON.stringify(data, null, 2));\n } else if (format === 'csv') {\n if (data.length === 0) {\n logger.error('No data to print');\n return;\n }\n\n console.log(formatCsv(data));\n } else if (format === 'jsonl') {\n data.forEach((item) => console.log(JSON.stringify(item)));\n } else {\n throw new Error(\n `Unsupported output format: ${String(format)}. `\n + \"(supported formats: json, csv, jsonl)\",\n );\n }\n};\n\n","/**\n * Write structured JSON to stdout. Use this for machine-readable output\n * when --json is set.\n */\nexport function outputJson(data: unknown): void {\n console.log(JSON.stringify(data));\n}\n\n/**\n * Write a JSON error to stdout and exit with code 1.\n * Use this in --json mode so agents can parse the failure.\n */\nexport function outputJsonError(error: unknown, exitCode: number = 1): never {\n console.log(JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n }));\n process.exit(exitCode);\n}\n","import { LaminarClient } from \"@lmnr-ai/client\";\nimport { Datapoint, type StringUUID } from \"@lmnr-ai/types\";\n\nimport { loadFromPaths, printToConsole, writeToFile } from \"../../utils/file\";\nimport { initializeLogger } from \"../../utils/logger\";\nimport { outputJson, outputJsonError } from \"../../utils/output\";\n\nconst logger = initializeLogger();\nconst DEFAULT_DATASET_PULL_BATCH_SIZE = 100;\nconst DEFAULT_DATASET_PUSH_BATCH_SIZE = 100;\n\ninterface DatasetCommandOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n json?: boolean;\n}\n\n/**\n * Pull all data from a dataset in batches.\n */\nconst pullAllData = async <D = any, T = any>(\n client: LaminarClient,\n identifier: { name?: string; id?: StringUUID },\n batchSize: number = DEFAULT_DATASET_PULL_BATCH_SIZE,\n offset: number = 0,\n limit?: number,\n): Promise<Datapoint<D, T>[]> => {\n let hasMore = true;\n let currentOffset = offset;\n const stopAt = limit !== undefined ? offset + limit : undefined;\n\n const result: Datapoint<D, T>[] = [];\n\n while (hasMore && (stopAt === undefined || currentOffset < stopAt)) {\n const data = await client.datasets.pull<D, T>({\n ...identifier,\n offset: currentOffset,\n limit: batchSize,\n });\n\n result.push(...data.items);\n\n // Stop if we received no items or fewer items than requested (end of data)\n if (data.items.length === 0 || data.items.length < batchSize) {\n hasMore = false;\n } else if (stopAt !== undefined && currentOffset + batchSize >= stopAt) {\n hasMore = false;\n } else if (data.totalCount !== undefined && currentOffset + batchSize >= data.totalCount) {\n hasMore = false;\n }\n\n currentOffset += batchSize;\n }\n\n if (limit !== undefined) {\n return result.slice(0, limit);\n }\n\n return result;\n};\n\n/**\n * Handle datasets list command.\n */\nexport const handleDatasetsList = async (\n options: DatasetCommandOptions,\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n const datasets = await client.datasets.listDatasets();\n\n if (options.json) {\n outputJson(datasets);\n return;\n }\n\n if (datasets.length === 0) {\n console.log(\"No datasets found.\");\n return;\n }\n\n // Print table header\n const idWidth = 36; // UUID length\n const createdAtWidth = 19; // YYYY-MM-DD HH:MM:SS format\n\n console.log(`\\n${'ID'.padEnd(idWidth)} ${'Created At'.padEnd(createdAtWidth)} Name`);\n console.log(`${'-'.repeat(idWidth)} ${'-'.repeat(createdAtWidth)} ${'-'.repeat(20)}`);\n\n // Print each dataset row\n for (const dataset of datasets) {\n const createdAt = new Date(dataset.createdAt);\n const createdAtStr = createdAt.toISOString().replace('T', ' ').substring(0, 19);\n console.log(\n `${dataset.id.padEnd(idWidth)} ${createdAtStr.padEnd(createdAtWidth)} ${dataset.name}`,\n );\n }\n\n console.log(`\\nTotal: ${datasets.length} dataset(s)\\n`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets push command.\n */\nexport const handleDatasetsPush = async (\n paths: string[],\n options: DatasetCommandOptions & {\n name?: string;\n id?: StringUUID;\n recursive?: boolean;\n batchSize?: number;\n },\n): Promise<void> => {\n if (!options.name && !options.id) {\n if (options.json) outputJsonError(\"Either name or id must be provided\");\n logger.error(\"Either name or id must be provided\");\n process.exit(1);\n }\n\n if (options.name && options.id) {\n if (options.json) outputJsonError(\"Only one of name or id must be provided\");\n logger.error(\"Only one of name or id must be provided\");\n process.exit(1);\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n\n try {\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n if (options.json) outputJsonError(\"No data to push\");\n logger.error(\"No data to push. Skipping\");\n process.exit(1);\n }\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n const result = await client.datasets.push({\n points: data,\n ...identifier,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n });\n\n if (options.json) {\n outputJson({ datasetId: result?.datasetId, count: data.length });\n return;\n }\n\n logger.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to push dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets pull command.\n */\nexport const handleDatasetsPull = async (\n outputPath: string | undefined,\n options: DatasetCommandOptions & {\n name?: string;\n id?: StringUUID;\n outputFormat?: 'json' | 'csv' | 'jsonl';\n batchSize?: number;\n limit?: number;\n offset?: number;\n },\n): Promise<void> => {\n if (!options.name && !options.id) {\n if (options.json) outputJsonError(\"Either name or id must be provided\");\n logger.error(\"Either name or id must be provided\");\n process.exit(1);\n }\n\n if (options.name && options.id) {\n if (options.json) outputJsonError(\"Only one of name or id must be provided\");\n logger.error(\"Only one of name or id must be provided\");\n process.exit(1);\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n try {\n const result = await pullAllData(\n client,\n identifier,\n options.batchSize ?? DEFAULT_DATASET_PULL_BATCH_SIZE,\n options.offset ?? 0,\n options.limit,\n );\n\n if (outputPath) {\n await writeToFile(outputPath, result, options.outputFormat);\n if (options.json) {\n outputJson({ path: outputPath, count: result.length });\n } else {\n logger.info(`Successfully pulled ${result.length} data points to ${outputPath}`);\n }\n } else {\n if (options.json) {\n outputJson(result);\n } else {\n printToConsole(result, options.outputFormat ?? 'json');\n }\n }\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to pull dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets create command.\n */\nexport const handleDatasetsCreate = async (\n name: string,\n paths: string[],\n options: DatasetCommandOptions & {\n outputFile: string;\n outputFormat?: 'json' | 'csv' | 'jsonl';\n recursive?: boolean;\n batchSize?: number;\n },\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n // Load data from input files\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n if (options.json) outputJsonError(\"No data to push\");\n logger.error(\"No data to push. Skipping\");\n process.exit(1);\n }\n\n // Push data to create/populate the dataset\n logger.info(`Pushing ${data.length} data points to dataset '${name}'...`);\n\n await client.datasets.push({\n points: data,\n name,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n createDataset: true,\n });\n logger.info(`Successfully pushed ${data.length} data points to dataset '${name}'`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to create dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n\n // Pull data back from the dataset\n logger.info(`Pulling data from dataset '${name}'...`);\n\n try {\n const result = await pullAllData(\n client,\n { name },\n options.batchSize ?? DEFAULT_DATASET_PULL_BATCH_SIZE,\n 0,\n undefined,\n );\n\n // Save to output file\n await writeToFile(options.outputFile, result, options.outputFormat);\n\n if (options.json) {\n outputJson({ name, path: options.outputFile, count: result.length });\n } else {\n logger.info(\n `Successfully created dataset '${name}' `\n + `and saved ${result.length} datapoints to ${options.outputFile}`,\n );\n }\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n \"Failed to pull dataset after creation: \"\n + `${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n","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 { 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/logger';\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/logger';\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/logger\";\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","import { LaminarClient } from \"@lmnr-ai/client\";\n\nimport { initializeLogger } from \"../../utils/logger\";\nimport { outputJson, outputJsonError } from \"../../utils/output\";\n\nconst logger = initializeLogger();\n\ninterface SqlCommandOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n json?: boolean;\n}\n\nexport const handleSqlQuery = async (\n query: string,\n options: SqlCommandOptions,\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n const rows = await client.sql.query(query);\n\n if (options.json) {\n outputJson(rows);\n return;\n }\n\n if (rows.length === 0) {\n console.log(\"No rows returned.\");\n return;\n }\n\n // TODO: is there a standard library for printing these types of tables?\n const columns = Object.keys(rows[0]);\n const widths = columns.map((col) =>\n rows.reduce((max, r) => Math.max(max, String(r[col] ?? \"\").length), col.length),\n );\n\n const header = columns.map((col, i) => col.padEnd(widths[i])).join(\" \");\n\n const divider = widths.map((w) => \"-\".repeat(w)).join(\" \");\n\n console.log(`\\n${header}`);\n console.log(divider);\n\n for (const row of rows) {\n console.log(columns.map((col, i) => String(row[col] ?? \"\").padEnd(widths[i])).join(\" \"));\n }\n\n console.log(`\\n${rows.length} row(s)\\n`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(`Query failed: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n};\n\n","export const SQL_SCHEMA_HELP = `\nAvailable tables:\n spans\n span_id (UUID), name (String), span_type (String: DEFAULT|LLM|TOOL),\n start_time (DateTime64), end_time (DateTime64), duration (Float64),\n input_cost (Float64), output_cost (Float64), total_cost (Float64),\n input_tokens (Int64), output_tokens (Int64), total_tokens (Int64),\n request_model (String), response_model (String), model (String),\n trace_id (UUID), provider (String), path (String),\n input (String), output (String), status (String),\n parent_span_id (UUID), attributes (String), tags (Array(String))\n\n traces\n id (UUID), start_time (DateTime64), end_time (DateTime64),\n input_tokens (Int64), output_tokens (Int64), total_tokens (Int64),\n input_cost (Float64), output_cost (Float64), total_cost (Float64),\n duration (Float64), metadata (String), session_id (String),\n user_id (String), status (String), top_span_id (UUID),\n top_span_name (String), top_span_type (String), trace_type (String),\n tags (Array(String)), has_browser_session (Bool)\n\n events\n id (UUID), type (String), name (String), span_id (UUID),\n timestamp (DateTime64), attributes (String)\n\n signal_events\n id (UUID), signal_id (UUID), trace_id (UUID), run_id (UUID),\n name (String), payload (String), timestamp (DateTime64)\n\n signal_runs\n signal_id (UUID), job_id (UUID), trigger_id (UUID), run_id (UUID),\n trace_id (UUID), status (String), event_id (UUID), updated_at (DateTime64)\n\n evaluation_datapoints\n id (UUID), evaluation_id (UUID), data (String), target (String),\n metadata (String), executor_output (String), index (UInt64),\n trace_id (UUID), group_id (String), scores (String),\n created_at (DateTime64), dataset_id (UUID),\n dataset_datapoint_id (UUID), dataset_datapoint_created_at (DateTime64)\n\n dataset_datapoints\n id (UUID), created_at (DateTime64), dataset_id (UUID),\n data (String), target (String), metadata (String)\n`;\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\n\nimport { version } from '../package.json';\nimport {\n handleDatasetsCreate,\n handleDatasetsList,\n handleDatasetsPull,\n handleDatasetsPush,\n} from './commands/dataset';\nimport { runDev } from './commands/dev';\nimport { handleSqlQuery } from './commands/sql';\nimport { SQL_SCHEMA_HELP } from './commands/sql/schema';\n\nasync function main() {\n const program = new Command();\n\n program\n .name('lmnr-cli')\n .description('CLI for the Laminar agent observability platform')\n .version(version, '-v, --version', 'display version number');\n\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 const datasetsCmd = program\n .command(\"dataset\")\n .description(\"Manage datasets\")\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(\n \"--port <port>\",\n \"Port for the Laminar API. Defaults to 443\",\n (val) => parseInt(val, 10),\n )\n .option(\"--json\", \"Output structured JSON to stdout\");\n\n // Datasets list command\n datasetsCmd\n .command(\"list\")\n .description(\"List all datasets\")\n .action(async (_options, cmd) => {\n await handleDatasetsList(cmd.optsWithGlobals());\n });\n\n // Datasets push command\n datasetsCmd\n .command(\"push\")\n .description(\"Push datapoints to an existing dataset\")\n .argument(\"<paths...>\", \"Paths to files or directories containing data to push\")\n .option(\"-n, --name <name>\", \"Name of the dataset (either name or id must be provided)\")\n .option(\"--id <id>\", \"ID of the dataset (either name or id must be provided)\")\n .option(\"-r, --recursive\", \"Recursively read files in directories\", false)\n .option(\n \"--batch-size <size>\",\n \"Batch size for pushing data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .action(async (paths: string[], _options, cmd) => {\n await handleDatasetsPush(paths, cmd.optsWithGlobals());\n });\n\n // Datasets pull command\n datasetsCmd\n .command(\"pull\")\n .description(\"Pull data from a dataset\")\n .argument(\"[output-path]\", \"Path to save the data. If not provided, prints to console\")\n .option(\"-n, --name <name>\", \"Name of the dataset (either name or id must be provided)\")\n .option(\"--id <id>\", \"ID of the dataset (either name or id must be provided)\")\n .option(\n \"--output-format <format>\",\n \"Output format (json, csv, jsonl). Inferred from file extension if not provided\",\n )\n .option(\n \"--batch-size <size>\",\n \"Batch size for pulling data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .option(\"--limit <limit>\", \"Limit number of datapoints to pull\", (val) => parseInt(val, 10))\n .option(\"--offset <offset>\", \"Offset for pagination\", (val) => parseInt(val, 10), 0)\n .action(async (outputPath: string | undefined, _options, cmd) => {\n await handleDatasetsPull(outputPath, cmd.optsWithGlobals());\n });\n\n // Datasets create command\n datasetsCmd\n .command(\"create\")\n .description(\"Create a dataset from input files\")\n .argument(\"<name>\", \"Name of the dataset to create\")\n .argument(\"<paths...>\", \"Paths to files or directories containing data to push\")\n .requiredOption(\"-o, --output-file <file>\", \"Path to save the pulled data\")\n .option(\n \"--output-format <format>\",\n \"Output format (json, csv, jsonl). Inferred from file extension if not provided\",\n )\n .option(\"-r, --recursive\", \"Recursively read files in directories\", false)\n .option(\n \"--batch-size <size>\",\n \"Batch size for pushing/pulling data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .action(async (name: string, paths: string[], _options, cmd) => {\n await handleDatasetsCreate(name, paths, cmd.optsWithGlobals());\n });\n\n\n const sqlCmd = program\n .command(\"sql\")\n .description(\"Run SQL queries against your Laminar project data\")\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(\n \"--port <port>\",\n \"Port for the Laminar API. Defaults to 443\",\n (val) => parseInt(val, 10),\n )\n .option(\"--json\", \"Output structured JSON to stdout\");\n\n sqlCmd\n .command(\"query\")\n .description(\"Execute a SQL query\")\n .argument(\"<query>\", \"SQL query string\")\n .action(async (query: string, _options, cmd) => {\n await handleSqlQuery(query, cmd.optsWithGlobals());\n })\n .addHelpText(\"after\", SQL_SCHEMA_HELP + `\nExamples:\n $ lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\"\n $ lmnr-cli sql query \"SELECT id, total_cost, status FROM traces LIMIT 20\"\n $ lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\" --json\n`);\n\n sqlCmd\n .command(\"schema\")\n .description(\"Show available tables and their columns\")\n .action(() => {\n process.stdout.write(SQL_SCHEMA_HELP);\n });\n\n program.addHelpText('after', `\nExamples:\n lmnr-cli dev agent.ts # Debugger TypeScript entrypoint\n lmnr-cli dev agent.py # Debugger Python script mode\n lmnr-cli dev -m src.agent # Debuger Python module mode\n lmnr-cli dataset list --json # List all datasets\n lmnr-cli dataset push data.jsonl -n my-dataset --json # Push data to a dataset\n lmnr-cli dataset pull output.jsonl -n my-dataset --json # Pull data from a dataset\n lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\" --json # Query spans\n lmnr-cli sql query \"SELECT t.id, s.name FROM traces t \\\n JOIN spans s ON t.id = s.trace_id LIMIT 20\" --json\n lmnr-cli sql schema # Show available tables\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":["fs","path","crypto","initializeLogger","logger$2","newUUID","logger$1","DEFAULT_DATASET_PUSH_BATCH_SIZE","logger","logger","collectedFiles: string[]","fs","parsed: any","results: any[]","result: Datapoint<D, T>[]","Table","logger","result: Datapoint<D, T>[]","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","logger","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/utils/logger.ts","../src/utils/file.ts","../src/utils/output.ts","../src/utils/table.ts","../src/commands/dataset/index.ts","../src/cache-server.ts","../src/sse-client.ts","../../types/dist/index.mjs","../src/subprocess/executor.ts","../src/worker-registry.ts","../src/commands/dev/metadata.ts","../src/commands/dev/index.ts","../src/commands/sql/index.ts","../src/commands/sql/schema.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.15\";\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 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 destination: 2,\n }),\n );\n}\n","import { Datapoint } from '@lmnr-ai/types';\nimport csv from 'csv-parser';\nimport { asString, generateCsv, mkConfig } from 'export-to-csv';\nimport { createReadStream } from 'fs';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nimport { initializeLogger } from './logger';\n\nconst logger = initializeLogger();\n\n/**\n * Check if a file has a supported extension.\n */\nconst isSupportedFile = (file: string): boolean => {\n const ext = path.extname(file).toLowerCase();\n return ['.json', '.csv', '.jsonl'].includes(ext);\n};\n\n/**\n * Collect all supported files from the given paths.\n * Handles both files and directories.\n */\nexport const collectFiles = async (\n paths: string[],\n recursive: boolean = false,\n): Promise<string[]> => {\n const collectedFiles: string[] = [];\n\n for (const filepath of paths) {\n try {\n const stats = await fs.stat(filepath);\n\n if (stats.isFile()) {\n if (isSupportedFile(filepath)) {\n collectedFiles.push(filepath);\n } else {\n logger.warn(`Skipping unsupported file type: ${filepath}`);\n }\n } else if (stats.isDirectory()) {\n const entries = await fs.readdir(filepath);\n\n for (const entry of entries) {\n const fullPath = path.join(filepath, entry);\n const entryStats = await fs.stat(fullPath);\n\n if (entryStats.isFile() && isSupportedFile(fullPath)) {\n collectedFiles.push(fullPath);\n } else if (recursive && entryStats.isDirectory()) {\n const subFiles = await collectFiles([fullPath], true);\n collectedFiles.push(...subFiles);\n }\n }\n }\n } catch (error) {\n logger.warn(\n `Path does not exist or is not accessible: ${filepath}. `\n + `Error: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return collectedFiles;\n};\n\n/**\n * Read a JSON file and return its contents.\n */\nconst readJsonFile = async (filepath: string): Promise<any[]> => {\n const content = await fs.readFile(filepath, 'utf-8');\n const parsed = JSON.parse(content);\n return Array.isArray(parsed) ? parsed : [parsed];\n};\n\n/**\n * Try to parse a string as JSON. If it fails, return the original string.\n */\nconst tryParseJson = (content: string): any => {\n // Don't try to parse if it's not a string or doesn't look like JSON\n if (typeof content !== 'string') {\n return content;\n }\n\n // If it doesn't start with { or [, it's probably not JSON\n const trimmed = content.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return content;\n }\n\n try {\n return JSON.parse(content);\n } catch (error) {\n logger.debug(\n `Error parsing JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n return content;\n }\n};\n\n/**\n * Parse each field in a CSV row, attempting to convert JSON strings back to objects.\n */\nconst parseCsvRow = (row: Record<string, string>): any => {\n const parsed: any = {};\n for (const [key, value] of Object.entries(row)) {\n parsed[key] = tryParseJson(value);\n }\n return parsed;\n};\n\n/**\n * Read a CSV file and return its contents as an array of objects.\n */\nconst readCsvFile = async (filepath: string): Promise<any[]> => new Promise((resolve, reject) => {\n const results: any[] = [];\n createReadStream(filepath)\n .pipe(csv())\n .on('data', (data) => results.push(parseCsvRow(data)))\n .on('end', () => resolve(results))\n .on('error', reject);\n});\n\n/**\n * Read a JSONL file and return its contents as an array of objects.\n */\nasync function readJsonlFile(filepath: string): Promise<any[]> {\n const content = await fs.readFile(filepath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim());\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return lines.map((line) => JSON.parse(line));\n}\n\n/**\n * Read a single file and return its contents.\n */\nasync function readFile(filepath: string): Promise<any[]> {\n const ext = path.extname(filepath).toLowerCase();\n\n if (ext === '.json') {\n return readJsonFile(filepath);\n } else if (ext === '.csv') {\n return readCsvFile(filepath);\n } else if (ext === '.jsonl') {\n return readJsonlFile(filepath);\n } else {\n throw new Error(`Unsupported file type: ${ext}`);\n }\n}\n\n/**\n * Load data from all files in the specified paths.\n */\nexport const loadFromPaths = async <D = any, T = any>(\n paths: string[],\n recursive: boolean = false,\n): Promise<Datapoint<D, T>[]> => {\n const files = await collectFiles(paths, recursive);\n\n if (files.length === 0) {\n logger.warn('No supported files found in the specified paths');\n return [];\n }\n\n logger.info(`Found ${files.length} file(s) to read`);\n\n const result: Datapoint<D, T>[] = [];\n\n for (const file of files) {\n try {\n const data = await readFile(file);\n result.push(...data);\n logger.info(`Read ${data.length} record(s) from ${file}`);\n } catch (error) {\n logger.error(\n `Error reading file ${file}: ${error instanceof Error ? error.message : String(error)}`,\n );\n throw error;\n }\n }\n\n return result;\n};\n\n/**\n * Write data to a JSON file.\n */\nconst writeJsonFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n const content = JSON.stringify(data, null, 2);\n await fs.writeFile(filepath, content, 'utf-8');\n};\n\n/**\n * Format data as a CSV string.\n */\nconst formatCsv = <D, T>(data: Datapoint<D, T>[]): string => {\n const formattedData = data.map(item =>\n Object.fromEntries(Object.entries(item).map(([key, value]) => [key, stringifyForCsv(value)]),\n ));\n\n const csvConfig = mkConfig({ useKeysAsHeaders: true });\n const csvOutput = generateCsv(csvConfig)(formattedData);\n return asString(csvOutput);\n};\n\n/**\n * Write data to a CSV file.\n */\nconst writeCsvFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n if (data.length === 0) {\n throw new Error('No data to write to CSV');\n }\n\n await fs.writeFile(filepath, formatCsv(data), 'utf-8');\n};\n\n/**\n * Write data to a JSONL file.\n */\nconst writeJsonlFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n): Promise<void> => {\n const lines = data.map((item) => JSON.stringify(item)).join('\\n');\n await fs.writeFile(filepath, lines + '\\n', 'utf-8');\n};\n\n/**\n * Write data to a file based on the file extension.\n */\nexport const writeToFile = async <D, T>(\n filepath: string,\n data: Datapoint<D, T>[],\n format?: 'json' | 'csv' | 'jsonl',\n): Promise<void> => {\n // Create parent directories if they don't exist\n const dir = path.dirname(filepath);\n await fs.mkdir(dir, { recursive: true });\n\n // Determine the format\n const ext = format ?? path.extname(filepath).slice(1);\n\n if (format && format !== path.extname(filepath).slice(1)) {\n logger.warn(\n `Output format ${format} does not match file extension ${path.extname(filepath).slice(1)}`,\n );\n }\n\n if (ext === 'json') {\n await writeJsonFile(filepath, data);\n } else if (ext === 'csv') {\n await writeCsvFile(filepath, data);\n } else if (ext === 'jsonl') {\n await writeJsonlFile(filepath, data);\n } else {\n throw new Error(`Unsupported output format: ${ext}`);\n }\n};\n\n/**\n * Convert a value to a CSV-safe string.\n * - Strings and numbers pass through\n * - null/undefined become empty strings\n * - Objects and arrays are stringified to JSON\n */\nconst stringifyForCsv = (value: any): string => {\n if (value === null || value === undefined) {\n return '';\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n // For objects and arrays, stringify to JSON\n return JSON.stringify(value);\n};\n\n/**\n * Print data to console in the specified format.\n */\nexport const printToConsole = <D, T>(\n data: Datapoint<D, T>[],\n format: 'json' | 'csv' | 'jsonl' = 'json',\n) => {\n if (format === 'json') {\n console.log(JSON.stringify(data, null, 2));\n } else if (format === 'csv') {\n if (data.length === 0) {\n logger.error('No data to print');\n return;\n }\n\n console.log(formatCsv(data));\n } else if (format === 'jsonl') {\n data.forEach((item) => console.log(JSON.stringify(item)));\n } else {\n throw new Error(\n `Unsupported output format: ${String(format)}. `\n + \"(supported formats: json, csv, jsonl)\",\n );\n }\n};\n\n","/**\n * Write structured JSON to stdout. Use this for machine-readable output\n * when --json is set.\n */\nexport function outputJson(data: unknown): void {\n console.log(JSON.stringify(data));\n}\n\n/**\n * Write a JSON error to stdout and exit with code 1.\n * Use this in --json mode so agents can parse the failure.\n */\nexport function outputJsonError(error: unknown, exitCode: number = 1): never {\n console.log(JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n }));\n process.exit(exitCode);\n}\n","import Table from \"cli-table3\";\n\nconst DEFAULT_TERMINAL_WIDTH = 80;\nconst PADDING_RIGHT = 2;\n\nconst noBorderChars = {\n top: \"\", \"top-mid\": \"\", \"top-left\": \"\", \"top-right\": \"\",\n bottom: \"\", \"bottom-mid\": \"\", \"bottom-left\": \"\", \"bottom-right\": \"\",\n left: \"\", \"left-mid\": \"\", mid: \"\", \"mid-mid\": \"\",\n right: \"\", \"right-mid\": \"\", middle: \"\",\n};\n\nfunction getTerminalWidth(): number {\n return process.stdout.columns || DEFAULT_TERMINAL_WIDTH;\n}\n\n/**\n * Calculate column widths that fit within the terminal width.\n * Distributes available space proportionally based on content width.\n */\nfunction fitColumnWidths(\n contentWidths: number[],\n terminalWidth: number,\n): number[] | undefined {\n // With no borders, overhead is just padding-right per column\n const overhead = contentWidths.length * PADDING_RIGHT;\n const totalContentWidth = contentWidths.reduce((sum, w) => sum + w, 0);\n\n if (totalContentWidth + overhead <= terminalWidth) {\n return undefined;\n }\n\n const availableContent = terminalWidth - overhead;\n const minColWidth = 5;\n\n // Return widths including padding, since cli-table3's colWidths includes padding\n return contentWidths.map((w) =>\n Math.max(\n minColWidth + PADDING_RIGHT,\n Math.floor((w / totalContentWidth) * availableContent) + PADDING_RIGHT,\n ),\n );\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (maxLen < 1) return str;\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 1) + \"\\u2026\";\n}\n\n/**\n * Render a borderless table from column headers and row data.\n * Automatically truncates content when the table exceeds terminal width.\n */\nexport function renderTable(head: string[], rows: string[][]): string {\n const terminalWidth = getTerminalWidth();\n\n const contentWidths = head.map((h, i) =>\n rows.reduce((max, row) => Math.max(max, (row[i] ?? \"\").length), h.length),\n );\n\n const colWidths = fitColumnWidths(contentWidths, terminalWidth);\n\n const truncatedHead = colWidths\n ? head.map((h, i) => truncate(h, colWidths[i] - PADDING_RIGHT))\n : head;\n\n const table = new Table({\n head: truncatedHead,\n chars: noBorderChars,\n style: {\n \"padding-left\": 0,\n \"padding-right\": PADDING_RIGHT,\n },\n ...(colWidths && { colWidths }),\n });\n\n if (colWidths) {\n for (const row of rows) {\n table.push(row.map((cell, i) => truncate(cell, colWidths[i] - PADDING_RIGHT)));\n }\n } else {\n for (const row of rows) {\n table.push(row);\n }\n }\n\n return table.toString();\n}\n","import { LaminarClient } from \"@lmnr-ai/client\";\nimport { Datapoint, type StringUUID } from \"@lmnr-ai/types\";\n\nimport { loadFromPaths, printToConsole, writeToFile } from \"../../utils/file\";\nimport { initializeLogger } from \"../../utils/logger\";\nimport { outputJson, outputJsonError } from \"../../utils/output\";\nimport { renderTable } from \"../../utils/table\";\n\nconst logger = initializeLogger();\nconst DEFAULT_DATASET_PULL_BATCH_SIZE = 100;\nconst DEFAULT_DATASET_PUSH_BATCH_SIZE = 100;\n\ninterface DatasetCommandOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n json?: boolean;\n}\n\n/**\n * Pull all data from a dataset in batches.\n */\nconst pullAllData = async <D = any, T = any>(\n client: LaminarClient,\n identifier: { name?: string; id?: StringUUID },\n batchSize: number = DEFAULT_DATASET_PULL_BATCH_SIZE,\n offset: number = 0,\n limit?: number,\n): Promise<Datapoint<D, T>[]> => {\n let hasMore = true;\n let currentOffset = offset;\n const stopAt = limit !== undefined ? offset + limit : undefined;\n\n const result: Datapoint<D, T>[] = [];\n\n while (hasMore && (stopAt === undefined || currentOffset < stopAt)) {\n const data = await client.datasets.pull<D, T>({\n ...identifier,\n offset: currentOffset,\n limit: batchSize,\n });\n\n result.push(...data.items);\n\n // Stop if we received no items or fewer items than requested (end of data)\n if (data.items.length === 0 || data.items.length < batchSize) {\n hasMore = false;\n } else if (stopAt !== undefined && currentOffset + batchSize >= stopAt) {\n hasMore = false;\n } else if (data.totalCount !== undefined && currentOffset + batchSize >= data.totalCount) {\n hasMore = false;\n }\n\n currentOffset += batchSize;\n }\n\n if (limit !== undefined) {\n return result.slice(0, limit);\n }\n\n return result;\n};\n\n/**\n * Handle datasets list command.\n */\nexport const handleDatasetsList = async (\n options: DatasetCommandOptions,\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n const datasets = await client.datasets.listDatasets();\n\n if (options.json) {\n outputJson(datasets);\n return;\n }\n\n if (datasets.length === 0) {\n console.log(\"No datasets found.\");\n return;\n }\n\n const rows = datasets.map((dataset) => {\n const createdAt = new Date(dataset.createdAt);\n const createdAtStr = createdAt.toISOString().replace('T', ' ').substring(0, 19);\n return [dataset.id, createdAtStr, dataset.name];\n });\n\n console.log(renderTable(['ID', 'Created At', 'Name'], rows));\n console.log(`\\nTotal: ${datasets.length} dataset(s)\\n`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets push command.\n */\nexport const handleDatasetsPush = async (\n paths: string[],\n options: DatasetCommandOptions & {\n name?: string;\n id?: StringUUID;\n recursive?: boolean;\n batchSize?: number;\n },\n): Promise<void> => {\n if (!options.name && !options.id) {\n if (options.json) outputJsonError(\"Either name or id must be provided\");\n logger.error(\"Either name or id must be provided\");\n process.exit(1);\n }\n\n if (options.name && options.id) {\n if (options.json) outputJsonError(\"Only one of name or id must be provided\");\n logger.error(\"Only one of name or id must be provided\");\n process.exit(1);\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n\n try {\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n if (options.json) outputJsonError(\"No data to push\");\n logger.error(\"No data to push. Skipping\");\n process.exit(1);\n }\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n const result = await client.datasets.push({\n points: data,\n ...identifier,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n });\n\n if (options.json) {\n outputJson({ datasetId: result?.datasetId, count: data.length });\n return;\n }\n\n logger.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to push dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets pull command.\n */\nexport const handleDatasetsPull = async (\n outputPath: string | undefined,\n options: DatasetCommandOptions & {\n name?: string;\n id?: StringUUID;\n outputFormat?: 'json' | 'csv' | 'jsonl';\n batchSize?: number;\n limit?: number;\n offset?: number;\n },\n): Promise<void> => {\n if (!options.name && !options.id) {\n if (options.json) outputJsonError(\"Either name or id must be provided\");\n logger.error(\"Either name or id must be provided\");\n process.exit(1);\n }\n\n if (options.name && options.id) {\n if (options.json) outputJsonError(\"Only one of name or id must be provided\");\n logger.error(\"Only one of name or id must be provided\");\n process.exit(1);\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n try {\n const result = await pullAllData(\n client,\n identifier,\n options.batchSize ?? DEFAULT_DATASET_PULL_BATCH_SIZE,\n options.offset ?? 0,\n options.limit,\n );\n\n if (outputPath) {\n await writeToFile(outputPath, result, options.outputFormat);\n if (options.json) {\n outputJson({ path: outputPath, count: result.length });\n } else {\n logger.info(`Successfully pulled ${result.length} data points to ${outputPath}`);\n }\n } else {\n if (options.json) {\n outputJson(result);\n } else {\n printToConsole(result, options.outputFormat ?? 'json');\n }\n }\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to pull dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n\n/**\n * Handle datasets create command.\n */\nexport const handleDatasetsCreate = async (\n name: string,\n paths: string[],\n options: DatasetCommandOptions & {\n outputFile: string;\n outputFormat?: 'json' | 'csv' | 'jsonl';\n recursive?: boolean;\n batchSize?: number;\n },\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n // Load data from input files\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n if (options.json) outputJsonError(\"No data to push\");\n logger.error(\"No data to push. Skipping\");\n process.exit(1);\n }\n\n // Push data to create/populate the dataset\n logger.info(`Pushing ${data.length} data points to dataset '${name}'...`);\n\n await client.datasets.push({\n points: data,\n name,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n createDataset: true,\n });\n logger.info(`Successfully pushed ${data.length} data points to dataset '${name}'`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n `Failed to create dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n\n // Pull data back from the dataset\n logger.info(`Pulling data from dataset '${name}'...`);\n\n try {\n const result = await pullAllData(\n client,\n { name },\n options.batchSize ?? DEFAULT_DATASET_PULL_BATCH_SIZE,\n 0,\n undefined,\n );\n\n // Save to output file\n await writeToFile(options.outputFile, result, options.outputFormat);\n\n if (options.json) {\n outputJson({ name, path: options.outputFile, count: result.length });\n } else {\n logger.info(\n `Successfully created dataset '${name}' `\n + `and saved ${result.length} datapoints to ${options.outputFile}`,\n );\n }\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(\n \"Failed to pull dataset after creation: \"\n + `${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n};\n","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 { 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/logger';\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/logger';\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/logger\";\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","import { LaminarClient } from \"@lmnr-ai/client\";\n\nimport { initializeLogger } from \"../../utils/logger\";\nimport { outputJson, outputJsonError } from \"../../utils/output\";\nimport { renderTable } from \"../../utils/table\";\n\nconst logger = initializeLogger();\n\ninterface SqlCommandOptions {\n projectApiKey?: string;\n baseUrl?: string;\n port?: number;\n json?: boolean;\n}\n\nexport const handleSqlQuery = async (\n query: string,\n options: SqlCommandOptions,\n): Promise<void> => {\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n try {\n const rows = await client.sql.query(query);\n\n if (options.json) {\n outputJson(rows);\n return;\n }\n\n if (rows.length === 0) {\n console.log(\"No rows returned.\");\n return;\n }\n\n const columns = Object.keys(rows[0]);\n const tableRows = rows.map((row) =>\n columns.map((col) => String(row[col] ?? \"\")),\n );\n\n console.log(renderTable(columns, tableRows));\n console.log(`\\n${rows.length} row(s)\\n`);\n } catch (error) {\n if (options.json) outputJsonError(error);\n logger.error(`Query failed: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n};\n\n","export const SQL_SCHEMA_HELP = `\nAvailable tables:\n spans\n span_id (UUID), name (String), span_type (String: DEFAULT|LLM|TOOL),\n start_time (DateTime64), end_time (DateTime64), duration (Float64),\n input_cost (Float64), output_cost (Float64), total_cost (Float64),\n input_tokens (Int64), output_tokens (Int64), total_tokens (Int64),\n request_model (String), response_model (String), model (String),\n trace_id (UUID), provider (String), path (String),\n input (String), output (String), status (String),\n parent_span_id (UUID), attributes (String), tags (Array(String))\n\n traces\n id (UUID), start_time (DateTime64), end_time (DateTime64),\n input_tokens (Int64), output_tokens (Int64), total_tokens (Int64),\n input_cost (Float64), output_cost (Float64), total_cost (Float64),\n duration (Float64), metadata (String), session_id (String),\n user_id (String), status (String), top_span_id (UUID),\n top_span_name (String), top_span_type (String), trace_type (String),\n tags (Array(String)), has_browser_session (Bool)\n\n events\n id (UUID), type (String), name (String), span_id (UUID),\n timestamp (DateTime64), attributes (String)\n\n signal_events\n id (UUID), signal_id (UUID), trace_id (UUID), run_id (UUID),\n name (String), payload (String), timestamp (DateTime64)\n\n signal_runs\n signal_id (UUID), job_id (UUID), trigger_id (UUID), run_id (UUID),\n trace_id (UUID), status (String), event_id (UUID), updated_at (DateTime64)\n\n evaluation_datapoints\n id (UUID), evaluation_id (UUID), data (String), target (String),\n metadata (String), executor_output (String), index (UInt64),\n trace_id (UUID), group_id (String), scores (String),\n created_at (DateTime64), dataset_id (UUID),\n dataset_datapoint_id (UUID), dataset_datapoint_created_at (DateTime64)\n\n dataset_datapoints\n id (UUID), created_at (DateTime64), dataset_id (UUID),\n data (String), target (String), metadata (String)\n`;\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\n\nimport { version } from '../package.json';\nimport {\n handleDatasetsCreate,\n handleDatasetsList,\n handleDatasetsPull,\n handleDatasetsPush,\n} from './commands/dataset';\nimport { runDev } from './commands/dev';\nimport { handleSqlQuery } from './commands/sql';\nimport { SQL_SCHEMA_HELP } from './commands/sql/schema';\n\nasync function main() {\n const program = new Command();\n\n program\n .name('lmnr-cli')\n .description('CLI for the Laminar agent observability platform')\n .version(version, '-v, --version', 'display version number');\n\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 const datasetsCmd = program\n .command(\"dataset\")\n .description(\"Manage datasets\")\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(\n \"--port <port>\",\n \"Port for the Laminar API. Defaults to 443\",\n (val) => parseInt(val, 10),\n )\n .option(\"--json\", \"Output structured JSON to stdout\");\n\n // Datasets list command\n datasetsCmd\n .command(\"list\")\n .description(\"List all datasets\")\n .action(async (_options, cmd) => {\n await handleDatasetsList(cmd.optsWithGlobals());\n });\n\n // Datasets push command\n datasetsCmd\n .command(\"push\")\n .description(\"Push datapoints to an existing dataset\")\n .argument(\"<paths...>\", \"Paths to files or directories containing data to push\")\n .option(\"-n, --name <name>\", \"Name of the dataset (either name or id must be provided)\")\n .option(\"--id <id>\", \"ID of the dataset (either name or id must be provided)\")\n .option(\"-r, --recursive\", \"Recursively read files in directories\", false)\n .option(\n \"--batch-size <size>\",\n \"Batch size for pushing data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .action(async (paths: string[], _options, cmd) => {\n await handleDatasetsPush(paths, cmd.optsWithGlobals());\n });\n\n // Datasets pull command\n datasetsCmd\n .command(\"pull\")\n .description(\"Pull data from a dataset\")\n .argument(\"[output-path]\", \"Path to save the data. If not provided, prints to console\")\n .option(\"-n, --name <name>\", \"Name of the dataset (either name or id must be provided)\")\n .option(\"--id <id>\", \"ID of the dataset (either name or id must be provided)\")\n .option(\n \"--output-format <format>\",\n \"Output format (json, csv, jsonl). Inferred from file extension if not provided\",\n )\n .option(\n \"--batch-size <size>\",\n \"Batch size for pulling data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .option(\"--limit <limit>\", \"Limit number of datapoints to pull\", (val) => parseInt(val, 10))\n .option(\"--offset <offset>\", \"Offset for pagination\", (val) => parseInt(val, 10), 0)\n .action(async (outputPath: string | undefined, _options, cmd) => {\n await handleDatasetsPull(outputPath, cmd.optsWithGlobals());\n });\n\n // Datasets create command\n datasetsCmd\n .command(\"create\")\n .description(\"Create a dataset from input files\")\n .argument(\"<name>\", \"Name of the dataset to create\")\n .argument(\"<paths...>\", \"Paths to files or directories containing data to push\")\n .requiredOption(\"-o, --output-file <file>\", \"Path to save the pulled data\")\n .option(\n \"--output-format <format>\",\n \"Output format (json, csv, jsonl). Inferred from file extension if not provided\",\n )\n .option(\"-r, --recursive\", \"Recursively read files in directories\", false)\n .option(\n \"--batch-size <size>\",\n \"Batch size for pushing/pulling data\",\n (val) => parseInt(val, 10),\n 100,\n )\n .action(async (name: string, paths: string[], _options, cmd) => {\n await handleDatasetsCreate(name, paths, cmd.optsWithGlobals());\n });\n\n\n const sqlCmd = program\n .command(\"sql\")\n .description(\"Run SQL queries against your Laminar project data\")\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(\n \"--port <port>\",\n \"Port for the Laminar API. Defaults to 443\",\n (val) => parseInt(val, 10),\n )\n .option(\"--json\", \"Output structured JSON to stdout\");\n\n sqlCmd\n .command(\"query\")\n .description(\"Execute a SQL query\")\n .argument(\"<query>\", \"SQL query string\")\n .action(async (query: string, _options, cmd) => {\n await handleSqlQuery(query, cmd.optsWithGlobals());\n })\n .addHelpText(\"after\", SQL_SCHEMA_HELP + `\nExamples:\n $ lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\"\n $ lmnr-cli sql query \"SELECT id, total_cost, status FROM traces LIMIT 20\"\n $ lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\" --json\n`);\n\n sqlCmd\n .command(\"schema\")\n .description(\"Show available tables and their columns\")\n .action(() => {\n process.stdout.write(SQL_SCHEMA_HELP);\n });\n\n program.addHelpText('after', `\nExamples:\n lmnr-cli dev agent.ts # Debugger TypeScript entrypoint\n lmnr-cli dev agent.py # Debugger Python script mode\n lmnr-cli dev -m src.agent # Debugger Python module mode\n lmnr-cli dataset list --json # List all datasets\n lmnr-cli dataset push data.jsonl -n my-dataset --json # Push data to a dataset\n lmnr-cli dataset pull output.jsonl -n my-dataset --json # Pull data from a dataset\n lmnr-cli sql query \"SELECT * FROM spans LIMIT 10\" --json # Query spans\n lmnr-cli sql query \"SELECT t.id, s.name FROM traces t JOIN spans s ON t.id = s.trace_id\" --json\n lmnr-cli sql schema # Show available tables\n`);\n\n await program.parseAsync();\n}\n\nmain().catch((err) => {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n});\n"],"x_google_ignoreList":[1,2],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lmnr-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "CLI for Laminar AI rollout debugging",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"bin": {
|
|
@@ -23,18 +23,19 @@
|
|
|
23
23
|
"license": "Apache-2.0",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"chokidar": "^5.0.0",
|
|
26
|
+
"cli-table3": "^0.6.5",
|
|
26
27
|
"commander": "^14.0.2",
|
|
28
|
+
"csv-parser": "^3.2.0",
|
|
27
29
|
"eventsource-parser": "^3.0.6",
|
|
30
|
+
"export-to-csv": "^1.4.0",
|
|
28
31
|
"pino": "9.12.0",
|
|
29
32
|
"pino-pretty": "^13.1.1",
|
|
30
|
-
"uuid": "^13.0.0"
|
|
31
|
-
"csv-parser": "^3.2.0",
|
|
32
|
-
"export-to-csv": "^1.4.0"
|
|
33
|
+
"uuid": "^13.0.0"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
|
-
"vitest": "^4.1.
|
|
36
|
-
"@lmnr-ai/
|
|
37
|
-
"@lmnr-ai/
|
|
36
|
+
"vitest": "^4.1.2",
|
|
37
|
+
"@lmnr-ai/types": "0.8.15",
|
|
38
|
+
"@lmnr-ai/client": "0.8.15"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"@lmnr-ai/lmnr": "*"
|