@lmnr-ai/lmnr 0.8.22 → 0.8.24
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/cli/worker/build.cjs +1 -1
- package/dist/cli/worker/build.cjs.map +1 -1
- package/dist/cli/worker/build.mjs +1 -1
- package/dist/cli/worker/build.mjs.map +1 -1
- package/dist/cli/worker/index.cjs +7 -6
- package/dist/cli/worker/index.cjs.map +1 -1
- package/dist/cli/worker/index.mjs +7 -6
- package/dist/cli/worker/index.mjs.map +1 -1
- package/dist/cli/worker/ts-parser.d.cts +1 -1
- package/dist/cli/worker/ts-parser.d.mts +1 -1
- package/dist/cli.cjs +9 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +9 -9
- package/dist/cli.mjs.map +1 -1
- package/dist/{decorators-CKzMiD2H.cjs → decorators-CP_wG-e2.cjs} +226 -137
- package/dist/decorators-CP_wG-e2.cjs.map +1 -0
- package/dist/{decorators-DrWG-1Po.mjs → decorators-DXckXv-B.mjs} +224 -129
- package/dist/decorators-DXckXv-B.mjs.map +1 -0
- package/dist/{dist-CzSNkDiM.cjs → dist-C2gKmm8d.cjs} +3 -3
- package/dist/{dist-CzSNkDiM.cjs.map → dist-C2gKmm8d.cjs.map} +1 -1
- package/dist/{dist-BXwORFgR.mjs → dist-CEeuq__5.mjs} +3 -3
- package/dist/{dist-BXwORFgR.mjs.map → dist-CEeuq__5.mjs.map} +1 -1
- package/dist/{evaluations-BJkIwpmH.d.cts → evaluations-CZwlO7xI.d.cts} +184 -5545
- package/dist/{evaluations-tqpNgp0P.d.mts → evaluations-RSSQZPfZ.d.mts} +184 -5545
- package/dist/{file-utils-yJ5ephze.cjs → file-utils-CQhJG7pP.cjs} +5 -5
- package/dist/file-utils-CQhJG7pP.cjs.map +1 -0
- package/dist/file-utils-DLLiBSon.cjs +2 -0
- package/dist/{file-utils-CHoR9VB8.mjs → file-utils-qcxtoRI-.mjs} +5 -5
- package/dist/file-utils-qcxtoRI-.mjs.map +1 -0
- package/dist/{index-Bal29BRz.d.cts → index-Dmd7gOUy.d.mts} +3 -2
- package/dist/{index-DSH1z3_q.d.mts → index-XPFtGLXV.d.cts} +3 -2
- package/dist/index.cjs +656 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -6
- package/dist/index.d.mts +131 -6
- package/dist/index.mjs +650 -11
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-C8Tl1vKD.cjs → utils-BOUPTptT.cjs} +31 -3
- package/dist/utils-BOUPTptT.cjs.map +1 -0
- package/dist/{utils-CHJ0KZUR.mjs → utils-C6favgeA.mjs} +20 -4
- package/dist/utils-C6favgeA.mjs.map +1 -0
- package/package.json +11 -12
- package/dist/decorators-CKzMiD2H.cjs.map +0 -1
- package/dist/decorators-DrWG-1Po.mjs.map +0 -1
- package/dist/file-utils-CHoR9VB8.mjs.map +0 -1
- package/dist/file-utils-IBEBwZxq.cjs +0 -2
- package/dist/file-utils-yJ5ephze.cjs.map +0 -1
- package/dist/utils-C8Tl1vKD.cjs.map +0 -1
- package/dist/utils-CHJ0KZUR.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Do9eywBl.cjs");
|
|
3
|
-
const require_utils = require("../../utils-
|
|
3
|
+
const require_utils = require("../../utils-BOUPTptT.cjs");
|
|
4
4
|
let path = require("path");
|
|
5
5
|
path = require_chunk.__toESM(path);
|
|
6
6
|
let fs = require("fs");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.cjs","names":["initializeLogger"],"sources":["../../../src/cli/worker/build.ts"],"sourcesContent":["import * as esbuild from 'esbuild';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { initializeLogger } from '../../utils';\n\nconst logger = initializeLogger();\n\n/**\n * esbuild plugin to load markdown files as raw strings\n */\nexport const rawMarkdownPlugin: esbuild.Plugin = {\n name: \"raw-markdown\",\n setup(build) {\n // Resolve .md imports\n build.onResolve({ filter: /\\.md$/ }, (args) => ({\n path: path.isAbsolute(args.path)\n ? args.path\n : path.resolve(args.resolveDir, args.path),\n namespace: \"raw-markdown\",\n }));\n\n // Load .md files as raw strings\n build.onLoad({ filter: /.*/, namespace: \"raw-markdown\" }, async (args) => {\n const content = await fs.promises.readFile(args.path, \"utf8\");\n // Escape backticks and backslashes in the content\n const escaped = content\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/`/g, \"\\\\`\")\n .replace(/\\$/g, \"\\\\$\");\n return {\n contents: `export default \\`${escaped}\\`;`,\n loader: \"js\",\n };\n });\n },\n};\n\n/**\n * esbuild plugin to skip dynamic imports\n */\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nexport interface BuildOptions {\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Builds a file using esbuild\n */\nexport async function buildFile(\n filePath: string,\n options?: BuildOptions,\n): Promise<string> {\n const result = await esbuild.build({\n bundle: true,\n platform: \"node\"
|
|
1
|
+
{"version":3,"file":"build.cjs","names":["initializeLogger"],"sources":["../../../src/cli/worker/build.ts"],"sourcesContent":["import * as esbuild from 'esbuild';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { initializeLogger } from '../../utils';\n\nconst logger = initializeLogger();\n\n/**\n * esbuild plugin to load markdown files as raw strings\n */\nexport const rawMarkdownPlugin: esbuild.Plugin = {\n name: \"raw-markdown\",\n setup(build) {\n // Resolve .md imports\n build.onResolve({ filter: /\\.md$/ }, (args) => ({\n path: path.isAbsolute(args.path)\n ? args.path\n : path.resolve(args.resolveDir, args.path),\n namespace: \"raw-markdown\",\n }));\n\n // Load .md files as raw strings\n build.onLoad({ filter: /.*/, namespace: \"raw-markdown\" }, async (args) => {\n const content = await fs.promises.readFile(args.path, \"utf8\");\n // Escape backticks and backslashes in the content\n const escaped = content\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/`/g, \"\\\\`\")\n .replace(/\\$/g, \"\\\\$\");\n return {\n contents: `export default \\`${escaped}\\`;`,\n loader: \"js\",\n };\n });\n },\n};\n\n/**\n * esbuild plugin to skip dynamic imports\n */\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nexport interface BuildOptions {\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Builds a file using esbuild\n */\nexport async function buildFile(\n filePath: string,\n options?: BuildOptions,\n): Promise<string> {\n const result = await esbuild.build({\n bundle: true,\n platform: \"node\",\n entryPoints: [filePath],\n outfile: `tmp_out_${filePath}.js`,\n write: false,\n external: [\n \"@lmnr-ai/*\",\n \"esbuild\",\n \"playwright\",\n \"puppeteer\",\n \"puppeteer-core\",\n \"playwright-core\",\n \"fsevents\",\n ...(options?.externalPackages ?? []),\n ],\n plugins: [\n rawMarkdownPlugin,\n createSkipDynamicImportsPlugin(options?.dynamicImportsToSkip ?? []),\n ],\n treeShaking: true,\n });\n\n if (!result.outputFiles || result.outputFiles.length === 0) {\n throw new Error(\"Failed to build file\");\n }\n\n return result.outputFiles[0].text;\n}\n\n/**\n * Loads and executes a module to register rollout functions\n */\nexport function loadModule({\n filename,\n moduleText,\n}: {\n filename: string;\n moduleText: string;\n}): void {\n globalThis._rolloutFunctions = new Map();\n globalThis._set_rollout_global = true;\n\n const __filename = filename;\n // Use the directory of the file being loaded, not the current dirname\n const __dirname = path.dirname(filename);\n\n /* eslint-disable @typescript-eslint/no-implied-eval */\n new Function(\n \"require\",\n \"module\",\n \"__filename\",\n \"__dirname\",\n moduleText,\n )(\n require,\n module,\n __filename,\n __dirname,\n );\n /* eslint-enable @typescript-eslint/no-implied-eval */\n}\n\n/**\n * Selects the appropriate rollout function from the registered functions\n */\nexport function selectRolloutFunction(\n requestedFunctionName?: string,\n): { fn: (...args: any[]) => any; params: any[]; name: string; exportName: string } {\n if (!globalThis._rolloutFunctions || globalThis._rolloutFunctions.size === 0) {\n throw new Error(\n \"No entrypoint functions found in file. \" +\n \" Make sure you are using observe with rolloutEntrypoint: true\",\n );\n }\n\n // If a specific function is requested, use that\n if (requestedFunctionName) {\n const selected = globalThis._rolloutFunctions.get(requestedFunctionName);\n if (!selected) {\n const available = Array.from(globalThis._rolloutFunctions.keys()).join(', ');\n throw new Error(\n `Function '${requestedFunctionName}' not found. Available functions: ${available}`,\n );\n }\n return { ...selected, exportName: requestedFunctionName };\n }\n\n // If only one function, auto-select it\n if (globalThis._rolloutFunctions.size === 1) {\n const [[exportName, selected]] = Array.from(globalThis._rolloutFunctions.entries());\n return { ...selected, exportName };\n }\n\n // Multiple functions found without explicit selection\n const available = Array.from(globalThis._rolloutFunctions.keys()).join(', ');\n throw new Error(\n `Multiple entrypoint functions found: ${available}.` +\n \" Use --function to specify which one to serve.\",\n );\n}\n"],"mappings":";;;;;;;;;;AAMA,MAAM,SAASA,cAAAA,kBAAkB;;;;AAKjC,MAAa,oBAAoC;CAC/C,MAAM;CACN,MAAM,OAAO;AAEX,QAAM,UAAU,EAAE,QAAQ,SAAS,GAAG,UAAU;GAC9C,MAAM,KAAK,WAAW,KAAK,KAAK,GAC5B,KAAK,OACL,KAAK,QAAQ,KAAK,YAAY,KAAK,KAAK;GAC5C,WAAW;GACZ,EAAE;AAGH,QAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;GAAgB,EAAE,OAAO,SAAS;AAOxE,UAAO;IACL,UAAU,qBAPI,MAAM,GAAG,SAAS,SAAS,KAAK,MAAM,OAAO,EAG1D,QAAQ,OAAO,OAAO,CACtB,QAAQ,MAAM,MAAM,CACpB,QAAQ,OAAO,MAAM,CAEgB;IACtC,QAAQ;IACT;IACD;;CAEL;;;;AAKD,MAAM,kCAAkC,iBAA2C;CACjF,MAAM;CACN,MAAM,OAAO;AACX,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG;AAE9C,QAAM,UAAU,EAAE,QAAQ,MAAM,GAAG,SAAS;AAE1C,OAAI,KAAK,SAAS,oBAAoB,YAAY,SAAS,KAAK,KAAK,EAAE;AACrE,WAAO,KAAK,4BAA4B,KAAK,OAAO;AAEpD,WAAO;KACL,MAAM,KAAK;KACX,WAAW;KACZ;;IAEH;AAIF,QAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;GAA4B,GAAG,UAAU;GAC/E,UAAU;GACV,QAAQ;GACT,EAAE;;CAEN;;;;AAUD,eAAsB,UACpB,UACA,SACiB;CACjB,MAAM,SAAS,MAAM,QAAQ,MAAM;EACjC,QAAQ;EACR,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,SAAS,WAAW,SAAS;EAC7B,OAAO;EACP,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAI,SAAS,oBAAoB,EAAE;GACpC;EACD,SAAS,CACP,mBACA,+BAA+B,SAAS,wBAAwB,EAAE,CAAC,CACpE;EACD,aAAa;EACd,CAAC;AAEF,KAAI,CAAC,OAAO,eAAe,OAAO,YAAY,WAAW,EACvD,OAAM,IAAI,MAAM,uBAAuB;AAGzC,QAAO,OAAO,YAAY,GAAG;;;;;AAM/B,SAAgB,WAAW,EACzB,UACA,cAIO;AACP,YAAW,oCAAoB,IAAI,KAAK;AACxC,YAAW,sBAAsB;CAEjC,MAAM,aAAa;CAEnB,MAAM,YAAY,KAAK,QAAQ,SAAS;AAGxC,KAAI,SACF,WACA,UACA,cACA,aACA,WACD,CACC,SACA,QACA,YACA,UACD;;;;;AAOH,SAAgB,sBACd,uBACkF;AAClF,KAAI,CAAC,WAAW,qBAAqB,WAAW,kBAAkB,SAAS,EACzE,OAAM,IAAI,MACR,uGAED;AAIH,KAAI,uBAAuB;EACzB,MAAM,WAAW,WAAW,kBAAkB,IAAI,sBAAsB;AACxE,MAAI,CAAC,UAAU;GACb,MAAM,YAAY,MAAM,KAAK,WAAW,kBAAkB,MAAM,CAAC,CAAC,KAAK,KAAK;AAC5E,SAAM,IAAI,MACR,aAAa,sBAAsB,oCAAoC,YACxE;;AAEH,SAAO;GAAE,GAAG;GAAU,YAAY;GAAuB;;AAI3D,KAAI,WAAW,kBAAkB,SAAS,GAAG;EAC3C,MAAM,CAAC,CAAC,YAAY,aAAa,MAAM,KAAK,WAAW,kBAAkB,SAAS,CAAC;AACnF,SAAO;GAAE,GAAG;GAAU;GAAY;;CAIpC,MAAM,YAAY,MAAM,KAAK,WAAW,kBAAkB,MAAM,CAAC,CAAC,KAAK,KAAK;AAC5E,OAAM,IAAI,MACR,wCAAwC,UAAU,iDAEnD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __require } from "../../chunk-BEJ448es.mjs";
|
|
2
|
-
import { s as initializeLogger } from "../../utils-
|
|
2
|
+
import { s as initializeLogger } from "../../utils-C6favgeA.mjs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as esbuild from "esbuild";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.mjs","names":[],"sources":["../../../src/cli/worker/build.ts"],"sourcesContent":["import * as esbuild from 'esbuild';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { initializeLogger } from '../../utils';\n\nconst logger = initializeLogger();\n\n/**\n * esbuild plugin to load markdown files as raw strings\n */\nexport const rawMarkdownPlugin: esbuild.Plugin = {\n name: \"raw-markdown\",\n setup(build) {\n // Resolve .md imports\n build.onResolve({ filter: /\\.md$/ }, (args) => ({\n path: path.isAbsolute(args.path)\n ? args.path\n : path.resolve(args.resolveDir, args.path),\n namespace: \"raw-markdown\",\n }));\n\n // Load .md files as raw strings\n build.onLoad({ filter: /.*/, namespace: \"raw-markdown\" }, async (args) => {\n const content = await fs.promises.readFile(args.path, \"utf8\");\n // Escape backticks and backslashes in the content\n const escaped = content\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/`/g, \"\\\\`\")\n .replace(/\\$/g, \"\\\\$\");\n return {\n contents: `export default \\`${escaped}\\`;`,\n loader: \"js\",\n };\n });\n },\n};\n\n/**\n * esbuild plugin to skip dynamic imports\n */\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nexport interface BuildOptions {\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Builds a file using esbuild\n */\nexport async function buildFile(\n filePath: string,\n options?: BuildOptions,\n): Promise<string> {\n const result = await esbuild.build({\n bundle: true,\n platform: \"node\"
|
|
1
|
+
{"version":3,"file":"build.mjs","names":[],"sources":["../../../src/cli/worker/build.ts"],"sourcesContent":["import * as esbuild from 'esbuild';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { initializeLogger } from '../../utils';\n\nconst logger = initializeLogger();\n\n/**\n * esbuild plugin to load markdown files as raw strings\n */\nexport const rawMarkdownPlugin: esbuild.Plugin = {\n name: \"raw-markdown\",\n setup(build) {\n // Resolve .md imports\n build.onResolve({ filter: /\\.md$/ }, (args) => ({\n path: path.isAbsolute(args.path)\n ? args.path\n : path.resolve(args.resolveDir, args.path),\n namespace: \"raw-markdown\",\n }));\n\n // Load .md files as raw strings\n build.onLoad({ filter: /.*/, namespace: \"raw-markdown\" }, async (args) => {\n const content = await fs.promises.readFile(args.path, \"utf8\");\n // Escape backticks and backslashes in the content\n const escaped = content\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/`/g, \"\\\\`\")\n .replace(/\\$/g, \"\\\\$\");\n return {\n contents: `export default \\`${escaped}\\`;`,\n loader: \"js\",\n };\n });\n },\n};\n\n/**\n * esbuild plugin to skip dynamic imports\n */\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nexport interface BuildOptions {\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Builds a file using esbuild\n */\nexport async function buildFile(\n filePath: string,\n options?: BuildOptions,\n): Promise<string> {\n const result = await esbuild.build({\n bundle: true,\n platform: \"node\",\n entryPoints: [filePath],\n outfile: `tmp_out_${filePath}.js`,\n write: false,\n external: [\n \"@lmnr-ai/*\",\n \"esbuild\",\n \"playwright\",\n \"puppeteer\",\n \"puppeteer-core\",\n \"playwright-core\",\n \"fsevents\",\n ...(options?.externalPackages ?? []),\n ],\n plugins: [\n rawMarkdownPlugin,\n createSkipDynamicImportsPlugin(options?.dynamicImportsToSkip ?? []),\n ],\n treeShaking: true,\n });\n\n if (!result.outputFiles || result.outputFiles.length === 0) {\n throw new Error(\"Failed to build file\");\n }\n\n return result.outputFiles[0].text;\n}\n\n/**\n * Loads and executes a module to register rollout functions\n */\nexport function loadModule({\n filename,\n moduleText,\n}: {\n filename: string;\n moduleText: string;\n}): void {\n globalThis._rolloutFunctions = new Map();\n globalThis._set_rollout_global = true;\n\n const __filename = filename;\n // Use the directory of the file being loaded, not the current dirname\n const __dirname = path.dirname(filename);\n\n /* eslint-disable @typescript-eslint/no-implied-eval */\n new Function(\n \"require\",\n \"module\",\n \"__filename\",\n \"__dirname\",\n moduleText,\n )(\n require,\n module,\n __filename,\n __dirname,\n );\n /* eslint-enable @typescript-eslint/no-implied-eval */\n}\n\n/**\n * Selects the appropriate rollout function from the registered functions\n */\nexport function selectRolloutFunction(\n requestedFunctionName?: string,\n): { fn: (...args: any[]) => any; params: any[]; name: string; exportName: string } {\n if (!globalThis._rolloutFunctions || globalThis._rolloutFunctions.size === 0) {\n throw new Error(\n \"No entrypoint functions found in file. \" +\n \" Make sure you are using observe with rolloutEntrypoint: true\",\n );\n }\n\n // If a specific function is requested, use that\n if (requestedFunctionName) {\n const selected = globalThis._rolloutFunctions.get(requestedFunctionName);\n if (!selected) {\n const available = Array.from(globalThis._rolloutFunctions.keys()).join(', ');\n throw new Error(\n `Function '${requestedFunctionName}' not found. Available functions: ${available}`,\n );\n }\n return { ...selected, exportName: requestedFunctionName };\n }\n\n // If only one function, auto-select it\n if (globalThis._rolloutFunctions.size === 1) {\n const [[exportName, selected]] = Array.from(globalThis._rolloutFunctions.entries());\n return { ...selected, exportName };\n }\n\n // Multiple functions found without explicit selection\n const available = Array.from(globalThis._rolloutFunctions.keys()).join(', ');\n throw new Error(\n `Multiple entrypoint functions found: ${available}.` +\n \" Use --function to specify which one to serve.\",\n );\n}\n"],"mappings":";;;;;;AAMA,MAAM,SAAS,kBAAkB;;;;AAKjC,MAAa,oBAAoC;CAC/C,MAAM;CACN,MAAM,OAAO;AAEX,QAAM,UAAU,EAAE,QAAQ,SAAS,GAAG,UAAU;GAC9C,MAAM,KAAK,WAAW,KAAK,KAAK,GAC5B,KAAK,OACL,KAAK,QAAQ,KAAK,YAAY,KAAK,KAAK;GAC5C,WAAW;GACZ,EAAE;AAGH,QAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;GAAgB,EAAE,OAAO,SAAS;AAOxE,UAAO;IACL,UAAU,qBAPI,MAAM,GAAG,SAAS,SAAS,KAAK,MAAM,OAAO,EAG1D,QAAQ,OAAO,OAAO,CACtB,QAAQ,MAAM,MAAM,CACpB,QAAQ,OAAO,MAAM,CAEgB;IACtC,QAAQ;IACT;IACD;;CAEL;;;;AAKD,MAAM,kCAAkC,iBAA2C;CACjF,MAAM;CACN,MAAM,OAAO;AACX,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG;AAE9C,QAAM,UAAU,EAAE,QAAQ,MAAM,GAAG,SAAS;AAE1C,OAAI,KAAK,SAAS,oBAAoB,YAAY,SAAS,KAAK,KAAK,EAAE;AACrE,WAAO,KAAK,4BAA4B,KAAK,OAAO;AAEpD,WAAO;KACL,MAAM,KAAK;KACX,WAAW;KACZ;;IAEH;AAIF,QAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;GAA4B,GAAG,UAAU;GAC/E,UAAU;GACV,QAAQ;GACT,EAAE;;CAEN;;;;AAUD,eAAsB,UACpB,UACA,SACiB;CACjB,MAAM,SAAS,MAAM,QAAQ,MAAM;EACjC,QAAQ;EACR,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,SAAS,WAAW,SAAS;EAC7B,OAAO;EACP,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAI,SAAS,oBAAoB,EAAE;GACpC;EACD,SAAS,CACP,mBACA,+BAA+B,SAAS,wBAAwB,EAAE,CAAC,CACpE;EACD,aAAa;EACd,CAAC;AAEF,KAAI,CAAC,OAAO,eAAe,OAAO,YAAY,WAAW,EACvD,OAAM,IAAI,MAAM,uBAAuB;AAGzC,QAAO,OAAO,YAAY,GAAG;;;;;AAM/B,SAAgB,WAAW,EACzB,UACA,cAIO;AACP,YAAW,oCAAoB,IAAI,KAAK;AACxC,YAAW,sBAAsB;CAEjC,MAAM,aAAa;CAEnB,MAAM,YAAY,KAAK,QAAQ,SAAS;AAGxC,KAAI,SACF,WACA,UACA,cACA,aACA,WACD,CAAA,WAEC,QACA,YACA,UACD;;;;;AAOH,SAAgB,sBACd,uBACkF;AAClF,KAAI,CAAC,WAAW,qBAAqB,WAAW,kBAAkB,SAAS,EACzE,OAAM,IAAI,MACR,uGAED;AAIH,KAAI,uBAAuB;EACzB,MAAM,WAAW,WAAW,kBAAkB,IAAI,sBAAsB;AACxE,MAAI,CAAC,UAAU;GACb,MAAM,YAAY,MAAM,KAAK,WAAW,kBAAkB,MAAM,CAAC,CAAC,KAAK,KAAK;AAC5E,SAAM,IAAI,MACR,aAAa,sBAAsB,oCAAoC,YACxE;;AAEH,SAAO;GAAE,GAAG;GAAU,YAAY;GAAuB;;AAI3D,KAAI,WAAW,kBAAkB,SAAS,GAAG;EAC3C,MAAM,CAAC,CAAC,YAAY,aAAa,MAAM,KAAK,WAAW,kBAAkB,SAAS,CAAC;AACnF,SAAO;GAAE,GAAG;GAAU;GAAY;;CAIpC,MAAM,YAAY,MAAM,KAAK,WAAW,kBAAkB,MAAM,CAAC,CAAC,KAAK,KAAK;AAC5E,OAAM,IAAI,MACR,wCAAwC,UAAU,iDAEnD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_chunk = require("../../chunk-Do9eywBl.cjs");
|
|
2
|
-
const
|
|
2
|
+
const require_utils = require("../../utils-BOUPTptT.cjs");
|
|
3
|
+
const require_decorators = require("../../decorators-CP_wG-e2.cjs");
|
|
3
4
|
const require_cli_worker_build = require("./build.cjs");
|
|
4
5
|
let readline = require("readline");
|
|
5
6
|
readline = require_chunk.__toESM(readline);
|
|
@@ -120,11 +121,11 @@ const main = () => {
|
|
|
120
121
|
if (require_decorators.Laminar.initialized()) await require_decorators.Laminar.flush();
|
|
121
122
|
process.exit(0);
|
|
122
123
|
} catch (error) {
|
|
123
|
-
await workerLogger.error(`Error in worker: ${
|
|
124
|
+
await workerLogger.error(`Error in worker: ${require_utils.errorMessage(error)}`);
|
|
124
125
|
if (require_decorators.Laminar.initialized()) await require_decorators.Laminar.flush();
|
|
125
126
|
await sendMessage({
|
|
126
127
|
type: "error",
|
|
127
|
-
error:
|
|
128
|
+
error: require_utils.errorMessage(error),
|
|
128
129
|
stack: error instanceof Error ? error.stack : void 0
|
|
129
130
|
});
|
|
130
131
|
process.exit(1);
|
|
@@ -132,7 +133,7 @@ const main = () => {
|
|
|
132
133
|
} catch (error) {
|
|
133
134
|
await sendMessage({
|
|
134
135
|
type: "error",
|
|
135
|
-
error: `Failed to parse config: ${
|
|
136
|
+
error: `Failed to parse config: ${require_utils.errorMessage(error)}`
|
|
136
137
|
});
|
|
137
138
|
process.exit(1);
|
|
138
139
|
}
|
|
@@ -149,7 +150,7 @@ const main = () => {
|
|
|
149
150
|
*/
|
|
150
151
|
const handleShutdown = () => {
|
|
151
152
|
if (require_decorators.Laminar.initialized()) require_decorators.Laminar.shutdown().catch((error) => {
|
|
152
|
-
workerLogger.error(`Error during Laminar shutdown: ${
|
|
153
|
+
workerLogger.error(`Error during Laminar shutdown: ${require_utils.errorMessage(error)}`).catch(() => {});
|
|
153
154
|
}).finally(() => {
|
|
154
155
|
process.exit(0);
|
|
155
156
|
});
|
|
@@ -162,7 +163,7 @@ try {
|
|
|
162
163
|
} catch (error) {
|
|
163
164
|
sendMessage({
|
|
164
165
|
type: "error",
|
|
165
|
-
error:
|
|
166
|
+
error: require_utils.errorMessage(error),
|
|
166
167
|
stack: error instanceof Error ? error.stack : void 0
|
|
167
168
|
}).then(() => process.exit(1));
|
|
168
169
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["buildFile","selectRolloutFunction","Laminar","consumeStreamResult"],"sources":["../../../src/cli/worker/index.ts"],"sourcesContent":["import * as readline from 'readline';\n\nimport { Laminar } from '../../laminar';\nimport { consumeStreamResult } from '../../opentelemetry-lib/tracing/stream-utils';\nimport { buildFile, loadModule, selectRolloutFunction } from './build';\n\n/**\n * Message types sent from child to parent via stdout\n */\ninterface LogMessage {\n type: 'log';\n level: 'info' | 'debug' | 'error' | 'warn';\n message: string;\n}\n\ninterface ErrorMessage {\n type: 'error';\n error: string;\n stack?: string;\n}\n\ntype WorkerMessage = LogMessage | ErrorMessage;\n\n/**\n * Configuration received from parent via stdin\n */\nexport interface WorkerConfig {\n filePath: string;\n functionName?: string;\n args: Record<string, any> | any[];\n env: Record<string, string>;\n cacheServerPort: number;\n baseUrl: string;\n projectApiKey?: string;\n httpPort: number;\n grpcPort: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Prefix for worker protocol messages to distinguish from user console.log output\n */\nconst WORKER_MESSAGE_PREFIX = '__LMNR_WORKER__:';\n\n/**\n * Sends a message to parent process via stdout.\n * Returns a Promise that resolves only once the data has been handed off to the\n * OS pipe buffer (via the write callback). This must be awaited before any\n * process.exit() call so that large messages are not truncated when Node.js\n * discards its internal stream buffers on exit.\n */\nconst sendMessage = (message: WorkerMessage): Promise<void> => new Promise((resolve) => {\n process.stdout.write(WORKER_MESSAGE_PREFIX + JSON.stringify(message) + '\\n', () => resolve());\n});\n\n/**\n * Logger that sends log messages to parent.\n * These are fire-and-forget: since stream writes are FIFO, awaiting the final\n * sendMessage (result/error) before exit is sufficient to flush all prior logs.\n */\nconst workerLogger = {\n info: async (message: string) => {\n await sendMessage({ type: 'log', level: 'info', message });\n },\n debug: async (message: string) => {\n await sendMessage({ type: 'log', level: 'debug', message });\n },\n error: async (message: string) => {\n await sendMessage({ type: 'log', level: 'error', message });\n },\n warn: async (message: string) => {\n await sendMessage({ type: 'log', level: 'warn', message });\n },\n};\n\n/**\n * Main worker execution function\n * Returns the result of the rollout function or throws an error\n */\nasync function runWorker(config: WorkerConfig): Promise<void> {\n // Set environment variables\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n\n await workerLogger.debug('Building user file...');\n const moduleText = await buildFile(config.filePath, {\n externalPackages: config.externalPackages,\n dynamicImportsToSkip: config.dynamicImportsToSkip,\n });\n\n await workerLogger.debug('Loading user file...');\n loadModule({\n filename: config.filePath,\n moduleText,\n });\n\n // Select the appropriate rollout function\n const selectedFunction = selectRolloutFunction(config.functionName);\n await workerLogger.debug(`Selected function: ${selectedFunction.name}`);\n\n // Initialize Laminar\n const urlWithoutSlash = config.baseUrl.replace(/\\/$/, '').replace(/:\\d{1,5}$/g, '');\n const baseHttpUrl = `${urlWithoutSlash}:${config.httpPort}`;\n\n if (!Laminar.initialized()) {\n await workerLogger.debug('Initializing Laminar...');\n Laminar.initialize({\n projectApiKey: config.projectApiKey,\n baseUrl: config.baseUrl,\n baseHttpUrl,\n httpPort: config.httpPort,\n grpcPort: config.grpcPort,\n disableBatch: true,\n });\n }\n\n // Execute the rollout function with args\n await workerLogger.debug('Executing entrypoint function...');\n\n const orderedArgs = Array.isArray(config.args)\n ? config.args\n : selectedFunction.params.map(param => {\n // Handle destructured parameters by reconstructing the object from nested properties\n if (param.nested && param.nested.length > 0) {\n const reconstructed: Record<string, any> = {};\n for (const nestedParam of param.nested) {\n reconstructed[nestedParam.name] = (config.args as Record<string, any>)[nestedParam.name];\n }\n return reconstructed;\n }\n // Regular parameter\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (config.args as Record<string, any>)[param.name];\n });\n await workerLogger.info(\n `Calling function ${selectedFunction.name} with args: ${JSON.stringify(orderedArgs)}`,\n );\n\n const rawResult = await selectedFunction.fn(...orderedArgs);\n\n // Consume the result if it's a stream to ensure background processing completes\n await workerLogger.debug('Consuming result (if stream)...');\n await consumeStreamResult(rawResult);\n\n await workerLogger.info('Function execution completed successfully');\n}\n\n/**\n * Read configuration from stdin and start worker\n * Centralized exit point for the worker process\n */\nconst main = () => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n let configReceived = false;\n\n // This function is called anyway, so it can be async.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n rl.on('line', async (line: string) => {\n if (configReceived) {\n return;\n }\n\n try {\n const config: WorkerConfig = JSON.parse(line);\n configReceived = true;\n rl.close();\n\n // Execute the worker and handle result/errors\n try {\n await runWorker(config);\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n // Exit successfully\n process.exit(0);\n } catch (error: any) {\n await workerLogger.error(\n `Error in worker: ${error instanceof Error ? error.message : error}`,\n );\n\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n await sendMessage({\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n process.exit(1);\n }\n } catch (error: any) {\n await sendMessage({\n type: 'error',\n error: `Failed to parse config: ${error instanceof Error ? error.message : error}`,\n });\n process.exit(1);\n }\n });\n\n rl.on('close', () => {\n if (!configReceived) {\n void sendMessage({\n type: 'error',\n error: 'No configuration received on stdin',\n }).then(() => process.exit(1));\n }\n });\n};\n\n/**\n * Handle graceful shutdown on SIGTERM/SIGINT\n */\nconst handleShutdown = () => {\n if (Laminar.initialized()) {\n Laminar.shutdown().catch((error: any) => {\n workerLogger.error(\n `Error during Laminar shutdown: ${error instanceof Error ? error.message : error}`,\n ).catch(() => { });\n }).finally(() => {\n process.exit(0);\n });\n } else {\n process.exit(0);\n }\n};\n\n// Register signal handlers\nprocess.on('SIGTERM', handleShutdown);\nprocess.on('SIGINT', handleShutdown);\n\n// Start the worker\ntry {\n main();\n} catch (error: any) {\n void sendMessage({\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }).then(() => process.exit(1));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["buildFile","selectRolloutFunction","Laminar","consumeStreamResult","errorMessage"],"sources":["../../../src/cli/worker/index.ts"],"sourcesContent":["import { errorMessage } from '@lmnr-ai/types';\nimport * as readline from 'readline';\n\nimport { Laminar } from '../../laminar';\nimport { consumeStreamResult } from '../../opentelemetry-lib/tracing/stream-utils';\nimport { buildFile, loadModule, selectRolloutFunction } from './build';\n\n/**\n * Message types sent from child to parent via stdout\n */\ninterface LogMessage {\n type: 'log';\n level: 'info' | 'debug' | 'error' | 'warn';\n message: string;\n}\n\ninterface ErrorMessage {\n type: 'error';\n error: string;\n stack?: string;\n}\n\ntype WorkerMessage = LogMessage | ErrorMessage;\n\n/**\n * Configuration received from parent via stdin\n */\nexport interface WorkerConfig {\n filePath: string;\n functionName?: string;\n args: Record<string, any> | any[];\n env: Record<string, string>;\n cacheServerPort: number;\n baseUrl: string;\n projectApiKey?: string;\n httpPort: number;\n grpcPort: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Prefix for worker protocol messages to distinguish from user console.log output\n */\nconst WORKER_MESSAGE_PREFIX = '__LMNR_WORKER__:';\n\n/**\n * Sends a message to parent process via stdout.\n * Returns a Promise that resolves only once the data has been handed off to the\n * OS pipe buffer (via the write callback). This must be awaited before any\n * process.exit() call so that large messages are not truncated when Node.js\n * discards its internal stream buffers on exit.\n */\nconst sendMessage = (message: WorkerMessage): Promise<void> => new Promise((resolve) => {\n process.stdout.write(WORKER_MESSAGE_PREFIX + JSON.stringify(message) + '\\n', () => resolve());\n});\n\n/**\n * Logger that sends log messages to parent.\n * These are fire-and-forget: since stream writes are FIFO, awaiting the final\n * sendMessage (result/error) before exit is sufficient to flush all prior logs.\n */\nconst workerLogger = {\n info: async (message: string) => {\n await sendMessage({ type: 'log', level: 'info', message });\n },\n debug: async (message: string) => {\n await sendMessage({ type: 'log', level: 'debug', message });\n },\n error: async (message: string) => {\n await sendMessage({ type: 'log', level: 'error', message });\n },\n warn: async (message: string) => {\n await sendMessage({ type: 'log', level: 'warn', message });\n },\n};\n\n/**\n * Main worker execution function\n * Returns the result of the rollout function or throws an error\n */\nasync function runWorker(config: WorkerConfig): Promise<void> {\n // Set environment variables\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n\n await workerLogger.debug('Building user file...');\n const moduleText = await buildFile(config.filePath, {\n externalPackages: config.externalPackages,\n dynamicImportsToSkip: config.dynamicImportsToSkip,\n });\n\n await workerLogger.debug('Loading user file...');\n loadModule({\n filename: config.filePath,\n moduleText,\n });\n\n // Select the appropriate rollout function\n const selectedFunction = selectRolloutFunction(config.functionName);\n await workerLogger.debug(`Selected function: ${selectedFunction.name}`);\n\n // Initialize Laminar\n const urlWithoutSlash = config.baseUrl.replace(/\\/$/, '').replace(/:\\d{1,5}$/g, '');\n const baseHttpUrl = `${urlWithoutSlash}:${config.httpPort}`;\n\n if (!Laminar.initialized()) {\n await workerLogger.debug('Initializing Laminar...');\n Laminar.initialize({\n projectApiKey: config.projectApiKey,\n baseUrl: config.baseUrl,\n baseHttpUrl,\n httpPort: config.httpPort,\n grpcPort: config.grpcPort,\n disableBatch: true,\n });\n }\n\n // Execute the rollout function with args\n await workerLogger.debug('Executing entrypoint function...');\n\n const orderedArgs = Array.isArray(config.args)\n ? config.args\n : selectedFunction.params.map(param => {\n // Handle destructured parameters by reconstructing the object from nested properties\n if (param.nested && param.nested.length > 0) {\n const reconstructed: Record<string, any> = {};\n for (const nestedParam of param.nested) {\n reconstructed[nestedParam.name] = (config.args as Record<string, any>)[nestedParam.name];\n }\n return reconstructed;\n }\n // Regular parameter\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (config.args as Record<string, any>)[param.name];\n });\n await workerLogger.info(\n `Calling function ${selectedFunction.name} with args: ${JSON.stringify(orderedArgs)}`,\n );\n\n const rawResult = await selectedFunction.fn(...orderedArgs);\n\n // Consume the result if it's a stream to ensure background processing completes\n await workerLogger.debug('Consuming result (if stream)...');\n await consumeStreamResult(rawResult);\n\n await workerLogger.info('Function execution completed successfully');\n}\n\n/**\n * Read configuration from stdin and start worker\n * Centralized exit point for the worker process\n */\nconst main = () => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n let configReceived = false;\n\n // This function is called anyway, so it can be async.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n rl.on('line', async (line: string) => {\n if (configReceived) {\n return;\n }\n\n try {\n const config: WorkerConfig = JSON.parse(line);\n configReceived = true;\n rl.close();\n\n // Execute the worker and handle result/errors\n try {\n await runWorker(config);\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n // Exit successfully\n process.exit(0);\n } catch (error: any) {\n await workerLogger.error(\n `Error in worker: ${errorMessage(error)}`,\n );\n\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n await sendMessage({\n type: 'error',\n error: errorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n process.exit(1);\n }\n } catch (error: any) {\n await sendMessage({\n type: 'error',\n error: `Failed to parse config: ${errorMessage(error)}`,\n });\n process.exit(1);\n }\n });\n\n rl.on('close', () => {\n if (!configReceived) {\n void sendMessage({\n type: 'error',\n error: 'No configuration received on stdin',\n }).then(() => process.exit(1));\n }\n });\n};\n\n/**\n * Handle graceful shutdown on SIGTERM/SIGINT\n */\nconst handleShutdown = () => {\n if (Laminar.initialized()) {\n Laminar.shutdown().catch((error: any) => {\n workerLogger.error(\n `Error during Laminar shutdown: ${errorMessage(error)}`,\n ).catch(() => { });\n }).finally(() => {\n process.exit(0);\n });\n } else {\n process.exit(0);\n }\n};\n\n// Register signal handlers\nprocess.on('SIGTERM', handleShutdown);\nprocess.on('SIGINT', handleShutdown);\n\n// Start the worker\ntry {\n main();\n} catch (error: any) {\n void sendMessage({\n type: 'error',\n error: errorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n }).then(() => process.exit(1));\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { R as errorMessage } from "../../utils-C6favgeA.mjs";
|
|
2
|
+
import { d as Laminar, h as consumeStreamResult } from "../../decorators-DXckXv-B.mjs";
|
|
2
3
|
import { buildFile, loadModule, selectRolloutFunction } from "./build.mjs";
|
|
3
4
|
import * as readline from "readline";
|
|
4
5
|
//#region src/cli/worker/index.ts
|
|
@@ -118,11 +119,11 @@ const main = () => {
|
|
|
118
119
|
if (Laminar.initialized()) await Laminar.flush();
|
|
119
120
|
process.exit(0);
|
|
120
121
|
} catch (error) {
|
|
121
|
-
await workerLogger.error(`Error in worker: ${error
|
|
122
|
+
await workerLogger.error(`Error in worker: ${errorMessage(error)}`);
|
|
122
123
|
if (Laminar.initialized()) await Laminar.flush();
|
|
123
124
|
await sendMessage({
|
|
124
125
|
type: "error",
|
|
125
|
-
error:
|
|
126
|
+
error: errorMessage(error),
|
|
126
127
|
stack: error instanceof Error ? error.stack : void 0
|
|
127
128
|
});
|
|
128
129
|
process.exit(1);
|
|
@@ -130,7 +131,7 @@ const main = () => {
|
|
|
130
131
|
} catch (error) {
|
|
131
132
|
await sendMessage({
|
|
132
133
|
type: "error",
|
|
133
|
-
error: `Failed to parse config: ${error
|
|
134
|
+
error: `Failed to parse config: ${errorMessage(error)}`
|
|
134
135
|
});
|
|
135
136
|
process.exit(1);
|
|
136
137
|
}
|
|
@@ -147,7 +148,7 @@ const main = () => {
|
|
|
147
148
|
*/
|
|
148
149
|
const handleShutdown = () => {
|
|
149
150
|
if (Laminar.initialized()) Laminar.shutdown().catch((error) => {
|
|
150
|
-
workerLogger.error(`Error during Laminar shutdown: ${error
|
|
151
|
+
workerLogger.error(`Error during Laminar shutdown: ${errorMessage(error)}`).catch(() => {});
|
|
151
152
|
}).finally(() => {
|
|
152
153
|
process.exit(0);
|
|
153
154
|
});
|
|
@@ -160,7 +161,7 @@ try {
|
|
|
160
161
|
} catch (error) {
|
|
161
162
|
sendMessage({
|
|
162
163
|
type: "error",
|
|
163
|
-
error:
|
|
164
|
+
error: errorMessage(error),
|
|
164
165
|
stack: error instanceof Error ? error.stack : void 0
|
|
165
166
|
}).then(() => process.exit(1));
|
|
166
167
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/cli/worker/index.ts"],"sourcesContent":["import * as readline from 'readline';\n\nimport { Laminar } from '../../laminar';\nimport { consumeStreamResult } from '../../opentelemetry-lib/tracing/stream-utils';\nimport { buildFile, loadModule, selectRolloutFunction } from './build';\n\n/**\n * Message types sent from child to parent via stdout\n */\ninterface LogMessage {\n type: 'log';\n level: 'info' | 'debug' | 'error' | 'warn';\n message: string;\n}\n\ninterface ErrorMessage {\n type: 'error';\n error: string;\n stack?: string;\n}\n\ntype WorkerMessage = LogMessage | ErrorMessage;\n\n/**\n * Configuration received from parent via stdin\n */\nexport interface WorkerConfig {\n filePath: string;\n functionName?: string;\n args: Record<string, any> | any[];\n env: Record<string, string>;\n cacheServerPort: number;\n baseUrl: string;\n projectApiKey?: string;\n httpPort: number;\n grpcPort: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Prefix for worker protocol messages to distinguish from user console.log output\n */\nconst WORKER_MESSAGE_PREFIX = '__LMNR_WORKER__:';\n\n/**\n * Sends a message to parent process via stdout.\n * Returns a Promise that resolves only once the data has been handed off to the\n * OS pipe buffer (via the write callback). This must be awaited before any\n * process.exit() call so that large messages are not truncated when Node.js\n * discards its internal stream buffers on exit.\n */\nconst sendMessage = (message: WorkerMessage): Promise<void> => new Promise((resolve) => {\n process.stdout.write(WORKER_MESSAGE_PREFIX + JSON.stringify(message) + '\\n', () => resolve());\n});\n\n/**\n * Logger that sends log messages to parent.\n * These are fire-and-forget: since stream writes are FIFO, awaiting the final\n * sendMessage (result/error) before exit is sufficient to flush all prior logs.\n */\nconst workerLogger = {\n info: async (message: string) => {\n await sendMessage({ type: 'log', level: 'info', message });\n },\n debug: async (message: string) => {\n await sendMessage({ type: 'log', level: 'debug', message });\n },\n error: async (message: string) => {\n await sendMessage({ type: 'log', level: 'error', message });\n },\n warn: async (message: string) => {\n await sendMessage({ type: 'log', level: 'warn', message });\n },\n};\n\n/**\n * Main worker execution function\n * Returns the result of the rollout function or throws an error\n */\nasync function runWorker(config: WorkerConfig): Promise<void> {\n // Set environment variables\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n\n await workerLogger.debug('Building user file...');\n const moduleText = await buildFile(config.filePath, {\n externalPackages: config.externalPackages,\n dynamicImportsToSkip: config.dynamicImportsToSkip,\n });\n\n await workerLogger.debug('Loading user file...');\n loadModule({\n filename: config.filePath,\n moduleText,\n });\n\n // Select the appropriate rollout function\n const selectedFunction = selectRolloutFunction(config.functionName);\n await workerLogger.debug(`Selected function: ${selectedFunction.name}`);\n\n // Initialize Laminar\n const urlWithoutSlash = config.baseUrl.replace(/\\/$/, '').replace(/:\\d{1,5}$/g, '');\n const baseHttpUrl = `${urlWithoutSlash}:${config.httpPort}`;\n\n if (!Laminar.initialized()) {\n await workerLogger.debug('Initializing Laminar...');\n Laminar.initialize({\n projectApiKey: config.projectApiKey,\n baseUrl: config.baseUrl,\n baseHttpUrl,\n httpPort: config.httpPort,\n grpcPort: config.grpcPort,\n disableBatch: true,\n });\n }\n\n // Execute the rollout function with args\n await workerLogger.debug('Executing entrypoint function...');\n\n const orderedArgs = Array.isArray(config.args)\n ? config.args\n : selectedFunction.params.map(param => {\n // Handle destructured parameters by reconstructing the object from nested properties\n if (param.nested && param.nested.length > 0) {\n const reconstructed: Record<string, any> = {};\n for (const nestedParam of param.nested) {\n reconstructed[nestedParam.name] = (config.args as Record<string, any>)[nestedParam.name];\n }\n return reconstructed;\n }\n // Regular parameter\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (config.args as Record<string, any>)[param.name];\n });\n await workerLogger.info(\n `Calling function ${selectedFunction.name} with args: ${JSON.stringify(orderedArgs)}`,\n );\n\n const rawResult = await selectedFunction.fn(...orderedArgs);\n\n // Consume the result if it's a stream to ensure background processing completes\n await workerLogger.debug('Consuming result (if stream)...');\n await consumeStreamResult(rawResult);\n\n await workerLogger.info('Function execution completed successfully');\n}\n\n/**\n * Read configuration from stdin and start worker\n * Centralized exit point for the worker process\n */\nconst main = () => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n let configReceived = false;\n\n // This function is called anyway, so it can be async.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n rl.on('line', async (line: string) => {\n if (configReceived) {\n return;\n }\n\n try {\n const config: WorkerConfig = JSON.parse(line);\n configReceived = true;\n rl.close();\n\n // Execute the worker and handle result/errors\n try {\n await runWorker(config);\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n // Exit successfully\n process.exit(0);\n } catch (error: any) {\n await workerLogger.error(\n `Error in worker: ${error instanceof Error ? error.message : error}`,\n );\n\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n await sendMessage({\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n process.exit(1);\n }\n } catch (error: any) {\n await sendMessage({\n type: 'error',\n error: `Failed to parse config: ${error instanceof Error ? error.message : error}`,\n });\n process.exit(1);\n }\n });\n\n rl.on('close', () => {\n if (!configReceived) {\n void sendMessage({\n type: 'error',\n error: 'No configuration received on stdin',\n }).then(() => process.exit(1));\n }\n });\n};\n\n/**\n * Handle graceful shutdown on SIGTERM/SIGINT\n */\nconst handleShutdown = () => {\n if (Laminar.initialized()) {\n Laminar.shutdown().catch((error: any) => {\n workerLogger.error(\n `Error during Laminar shutdown: ${error instanceof Error ? error.message : error}`,\n ).catch(() => { });\n }).finally(() => {\n process.exit(0);\n });\n } else {\n process.exit(0);\n }\n};\n\n// Register signal handlers\nprocess.on('SIGTERM', handleShutdown);\nprocess.on('SIGINT', handleShutdown);\n\n// Start the worker\ntry {\n main();\n} catch (error: any) {\n void sendMessage({\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }).then(() => process.exit(1));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/cli/worker/index.ts"],"sourcesContent":["import { errorMessage } from '@lmnr-ai/types';\nimport * as readline from 'readline';\n\nimport { Laminar } from '../../laminar';\nimport { consumeStreamResult } from '../../opentelemetry-lib/tracing/stream-utils';\nimport { buildFile, loadModule, selectRolloutFunction } from './build';\n\n/**\n * Message types sent from child to parent via stdout\n */\ninterface LogMessage {\n type: 'log';\n level: 'info' | 'debug' | 'error' | 'warn';\n message: string;\n}\n\ninterface ErrorMessage {\n type: 'error';\n error: string;\n stack?: string;\n}\n\ntype WorkerMessage = LogMessage | ErrorMessage;\n\n/**\n * Configuration received from parent via stdin\n */\nexport interface WorkerConfig {\n filePath: string;\n functionName?: string;\n args: Record<string, any> | any[];\n env: Record<string, string>;\n cacheServerPort: number;\n baseUrl: string;\n projectApiKey?: string;\n httpPort: number;\n grpcPort: number;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n}\n\n/**\n * Prefix for worker protocol messages to distinguish from user console.log output\n */\nconst WORKER_MESSAGE_PREFIX = '__LMNR_WORKER__:';\n\n/**\n * Sends a message to parent process via stdout.\n * Returns a Promise that resolves only once the data has been handed off to the\n * OS pipe buffer (via the write callback). This must be awaited before any\n * process.exit() call so that large messages are not truncated when Node.js\n * discards its internal stream buffers on exit.\n */\nconst sendMessage = (message: WorkerMessage): Promise<void> => new Promise((resolve) => {\n process.stdout.write(WORKER_MESSAGE_PREFIX + JSON.stringify(message) + '\\n', () => resolve());\n});\n\n/**\n * Logger that sends log messages to parent.\n * These are fire-and-forget: since stream writes are FIFO, awaiting the final\n * sendMessage (result/error) before exit is sufficient to flush all prior logs.\n */\nconst workerLogger = {\n info: async (message: string) => {\n await sendMessage({ type: 'log', level: 'info', message });\n },\n debug: async (message: string) => {\n await sendMessage({ type: 'log', level: 'debug', message });\n },\n error: async (message: string) => {\n await sendMessage({ type: 'log', level: 'error', message });\n },\n warn: async (message: string) => {\n await sendMessage({ type: 'log', level: 'warn', message });\n },\n};\n\n/**\n * Main worker execution function\n * Returns the result of the rollout function or throws an error\n */\nasync function runWorker(config: WorkerConfig): Promise<void> {\n // Set environment variables\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n\n await workerLogger.debug('Building user file...');\n const moduleText = await buildFile(config.filePath, {\n externalPackages: config.externalPackages,\n dynamicImportsToSkip: config.dynamicImportsToSkip,\n });\n\n await workerLogger.debug('Loading user file...');\n loadModule({\n filename: config.filePath,\n moduleText,\n });\n\n // Select the appropriate rollout function\n const selectedFunction = selectRolloutFunction(config.functionName);\n await workerLogger.debug(`Selected function: ${selectedFunction.name}`);\n\n // Initialize Laminar\n const urlWithoutSlash = config.baseUrl.replace(/\\/$/, '').replace(/:\\d{1,5}$/g, '');\n const baseHttpUrl = `${urlWithoutSlash}:${config.httpPort}`;\n\n if (!Laminar.initialized()) {\n await workerLogger.debug('Initializing Laminar...');\n Laminar.initialize({\n projectApiKey: config.projectApiKey,\n baseUrl: config.baseUrl,\n baseHttpUrl,\n httpPort: config.httpPort,\n grpcPort: config.grpcPort,\n disableBatch: true,\n });\n }\n\n // Execute the rollout function with args\n await workerLogger.debug('Executing entrypoint function...');\n\n const orderedArgs = Array.isArray(config.args)\n ? config.args\n : selectedFunction.params.map(param => {\n // Handle destructured parameters by reconstructing the object from nested properties\n if (param.nested && param.nested.length > 0) {\n const reconstructed: Record<string, any> = {};\n for (const nestedParam of param.nested) {\n reconstructed[nestedParam.name] = (config.args as Record<string, any>)[nestedParam.name];\n }\n return reconstructed;\n }\n // Regular parameter\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (config.args as Record<string, any>)[param.name];\n });\n await workerLogger.info(\n `Calling function ${selectedFunction.name} with args: ${JSON.stringify(orderedArgs)}`,\n );\n\n const rawResult = await selectedFunction.fn(...orderedArgs);\n\n // Consume the result if it's a stream to ensure background processing completes\n await workerLogger.debug('Consuming result (if stream)...');\n await consumeStreamResult(rawResult);\n\n await workerLogger.info('Function execution completed successfully');\n}\n\n/**\n * Read configuration from stdin and start worker\n * Centralized exit point for the worker process\n */\nconst main = () => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n let configReceived = false;\n\n // This function is called anyway, so it can be async.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n rl.on('line', async (line: string) => {\n if (configReceived) {\n return;\n }\n\n try {\n const config: WorkerConfig = JSON.parse(line);\n configReceived = true;\n rl.close();\n\n // Execute the worker and handle result/errors\n try {\n await runWorker(config);\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n // Exit successfully\n process.exit(0);\n } catch (error: any) {\n await workerLogger.error(\n `Error in worker: ${errorMessage(error)}`,\n );\n\n if (Laminar.initialized()) {\n await Laminar.flush();\n }\n\n await sendMessage({\n type: 'error',\n error: errorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n process.exit(1);\n }\n } catch (error: any) {\n await sendMessage({\n type: 'error',\n error: `Failed to parse config: ${errorMessage(error)}`,\n });\n process.exit(1);\n }\n });\n\n rl.on('close', () => {\n if (!configReceived) {\n void sendMessage({\n type: 'error',\n error: 'No configuration received on stdin',\n }).then(() => process.exit(1));\n }\n });\n};\n\n/**\n * Handle graceful shutdown on SIGTERM/SIGINT\n */\nconst handleShutdown = () => {\n if (Laminar.initialized()) {\n Laminar.shutdown().catch((error: any) => {\n workerLogger.error(\n `Error during Laminar shutdown: ${errorMessage(error)}`,\n ).catch(() => { });\n }).finally(() => {\n process.exit(0);\n });\n } else {\n process.exit(0);\n }\n};\n\n// Register signal handlers\nprocess.on('SIGTERM', handleShutdown);\nprocess.on('SIGINT', handleShutdown);\n\n// Start the worker\ntry {\n main();\n} catch (error: any) {\n void sendMessage({\n type: 'error',\n error: errorMessage(error),\n stack: error instanceof Error ? error.stack : undefined,\n }).then(() => process.exit(1));\n}\n"],"mappings":"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"}
|
package/dist/cli.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const require_chunk = require("./chunk-Do9eywBl.cjs");
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const require_file_utils = require("./file-utils-
|
|
3
|
+
const require_utils = require("./utils-BOUPTptT.cjs");
|
|
4
|
+
const require_dist = require("./dist-C2gKmm8d.cjs");
|
|
5
|
+
const require_file_utils = require("./file-utils-CQhJG7pP.cjs");
|
|
6
6
|
const require_proxy_to_lmnr_cli = require("./proxy-to-lmnr-cli-OA7sXzcz.cjs");
|
|
7
7
|
let fs = require("fs");
|
|
8
8
|
fs = require_chunk.__toESM(fs);
|
|
@@ -63,7 +63,7 @@ const handleDatasetsList = async (options) => {
|
|
|
63
63
|
}
|
|
64
64
|
console.log(`\nTotal: ${datasets.length} dataset(s)\n`);
|
|
65
65
|
} catch (error) {
|
|
66
|
-
logger$2.error(`Failed to list datasets: ${
|
|
66
|
+
logger$2.error(`Failed to list datasets: ${require_utils.errorMessage(error)}`);
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
/**
|
|
@@ -97,7 +97,7 @@ const handleDatasetsPush = async (paths, options) => {
|
|
|
97
97
|
});
|
|
98
98
|
logger$2.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);
|
|
99
99
|
} catch (error) {
|
|
100
|
-
logger$2.error(`Failed to push dataset: ${
|
|
100
|
+
logger$2.error(`Failed to push dataset: ${require_utils.errorMessage(error)}`);
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
/**
|
|
@@ -125,7 +125,7 @@ const handleDatasetsPull = async (outputPath, options) => {
|
|
|
125
125
|
logger$2.info(`Successfully pulled ${result.length} data points to ${outputPath}`);
|
|
126
126
|
} else require_file_utils.printToConsole(result, options.outputFormat ?? "json");
|
|
127
127
|
} catch (error) {
|
|
128
|
-
logger$2.error(`Failed to pull dataset: ${
|
|
128
|
+
logger$2.error(`Failed to pull dataset: ${require_utils.errorMessage(error)}`);
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
131
|
/**
|
|
@@ -152,7 +152,7 @@ const handleDatasetsCreate = async (name, paths, options) => {
|
|
|
152
152
|
});
|
|
153
153
|
logger$2.info(`Successfully pushed ${data.length} data points to dataset '${name}'`);
|
|
154
154
|
} catch (error) {
|
|
155
|
-
logger$2.error(`Failed to create dataset: ${
|
|
155
|
+
logger$2.error(`Failed to create dataset: ${require_utils.errorMessage(error)}`);
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
logger$2.info(`Pulling data from dataset '${name}'...`);
|
|
@@ -161,7 +161,7 @@ const handleDatasetsCreate = async (name, paths, options) => {
|
|
|
161
161
|
await require_file_utils.writeToFile(options.outputFile, result, options.outputFormat);
|
|
162
162
|
logger$2.info(`Successfully created dataset '${name}' and saved ${result.length} datapoints to ${options.outputFile}`);
|
|
163
163
|
} catch (error) {
|
|
164
|
-
logger$2.error(
|
|
164
|
+
logger$2.error("Failed to pull dataset after creation: " + require_utils.errorMessage(error));
|
|
165
165
|
}
|
|
166
166
|
};
|
|
167
167
|
//#endregion
|
|
@@ -313,7 +313,7 @@ async function cli() {
|
|
|
313
313
|
await program.parseAsync();
|
|
314
314
|
}
|
|
315
315
|
cli().catch((err) => {
|
|
316
|
-
logger.error(
|
|
316
|
+
logger.error(require_utils.errorMessage(err));
|
|
317
317
|
throw err;
|
|
318
318
|
});
|
|
319
319
|
//#endregion
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["logger","initializeLogger","LaminarClient","loadFromPaths","writeToFile","logger","initializeLogger","getDirname","initializeLogger","Command","version"],"sources":["../src/cli/datasets.ts","../src/cli/evals.ts","../src/cli/index.ts"],"sourcesContent":["import { LaminarClient } from \"@lmnr-ai/client\";\nimport { type StringUUID } from \"@lmnr-ai/types\";\n\nimport { Datapoint } from \"../evaluations\";\nimport { initializeLogger } from \"../utils\";\nimport { loadFromPaths, printToConsole, writeToFile } from \"./file-utils\";\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}\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 (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 logger.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n );\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 logger.error(\"Either name or id must be provided\");\n return;\n }\n\n if (options.name && options.id) {\n logger.error(\"Only one of name or id must be provided\");\n return;\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n logger.warn(\"No data to push. Skipping\");\n return;\n }\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n try {\n await client.datasets.push({\n points: data,\n ...identifier,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n });\n logger.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);\n } catch (error) {\n logger.error(\n `Failed to push dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\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 logger.error(\"Either name or id must be provided\");\n return;\n }\n\n if (options.name && options.id) {\n logger.error(\"Only one of name or id must be provided\");\n return;\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 logger.info(`Successfully pulled ${result.length} data points to ${outputPath}`);\n } else {\n printToConsole(result, options.outputFormat ?? 'json');\n }\n } catch (error) {\n logger.error(\n `Failed to pull dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\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 // Load data from input files\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n logger.warn(\"No data to push. Skipping\");\n return;\n }\n\n // Push data to create/populate the dataset\n logger.info(`Pushing ${data.length} data points to dataset '${name}'...`);\n\n try {\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 logger.error(\n `Failed to create dataset: ${error instanceof Error ? error.message : String(error)}`,\n );\n return;\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 logger.info(\n `Successfully created dataset '${name}' `\n + `and saved ${result.length} datapoints to ${options.outputFile}`,\n );\n } catch (error) {\n logger.error(\n \"Failed to pull dataset after creation: \"\n + `${error instanceof Error ? error.message : String(error)}`,\n );\n }\n};\n\n","import * as esbuild from \"esbuild\";\nimport * as fs from \"fs\";\nimport * as glob from \"glob\";\n\nimport { Evaluation } from \"../evaluations\";\nimport { getDirname, initializeLogger } from \"../utils\";\n\nconst logger = initializeLogger();\n\n// esbuild plugin to skip dynamic imports\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nfunction loadModule({\n filename,\n moduleText,\n}: {\n filename: string;\n moduleText: string;\n}): Evaluation<any, any, any>[] {\n globalThis._evaluations = [];\n globalThis._set_global_evaluation = true;\n\n const __filename = filename;\n const __dirname = getDirname();\n\n // add some arguments for proper cjs/esm interop\n\n /* eslint-disable @typescript-eslint/no-implied-eval */\n new Function(\n \"require\",\n \"module\",\n \"__filename\",\n \"__dirname\",\n moduleText,\n )(\n require,\n module,\n __filename,\n __dirname,\n );\n /* eslint-enable @typescript-eslint/no-implied-eval */\n\n // Return the modified _evals global variable\n return globalThis._evaluations;\n}\n\nexport interface EvalCommandOptions {\n failOnError?: boolean;\n outputFile?: string;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n frontendPort?: number;\n}\n\nexport async function runEvaluation(\n files: string[],\n options: EvalCommandOptions,\n): Promise<void> {\n let evalFiles: string[];\n if (files && files.length > 0) {\n evalFiles = files.flatMap((file: string) => glob.sync(file));\n } else {\n // No files provided, use default pattern\n evalFiles = glob.sync('evals/**/*.eval.{ts,js}');\n }\n\n evalFiles.sort();\n\n if (evalFiles.length === 0) {\n logger.error(\"No evaluation files found. Please provide a file or \" +\n \"ensure there are eval files that are named like `*.eval.{ts,js}` in \" +\n \"the `evals` directory or its subdirectories.\");\n process.exit(1);\n }\n\n if (files.length === 0) {\n logger.info(`Located ${evalFiles.length} evaluation files in evals/`);\n } else {\n logger.info(`Running ${evalFiles.length} evaluation files.`);\n }\n\n const scores: {\n file: string,\n scores: Record<string, number>,\n url: string,\n evaluationId: string,\n }[] = [];\n\n for (const file of evalFiles) {\n logger.info(`Loading ${file}...`);\n const buildOptions = {\n bundle: true,\n platform: \"node\" as esbuild.Platform,\n entryPoints: [file],\n outfile: `tmp_out_${file}.js`,\n write: false, // will be loaded in memory as a temp file\n external: [\n \"@lmnr-ai/lmnr\",\n \"@lmnr-ai/lmnr/*\",\n \"@lmnr-ai/client\",\n \"@lmnr-ai/types\",\n \"esbuild\",\n \"fsevents\",\n \"playwright\",\n \"puppeteer\",\n \"puppeteer-core\",\n \"playwright-core\",\n ...(options.externalPackages ? options.externalPackages : []),\n ],\n plugins: [\n createSkipDynamicImportsPlugin(options.dynamicImportsToSkip || []),\n ],\n treeShaking: true,\n };\n\n const result = await esbuild.build(buildOptions);\n\n if (!result.outputFiles) {\n logger.error(\"Error when building: No output files found \" +\n \"it is likely that all eval files are not valid TypeScript or JavaScript files.\");\n if (options.failOnError) {\n process.exit(1);\n }\n continue;\n }\n\n const outputFileText = result.outputFiles[0].text;\n\n const evaluations = loadModule({\n filename: file,\n moduleText: outputFileText,\n });\n\n logger.info(`Loaded ${evaluations.length} evaluations from ${file}`);\n\n for (const evaluation of evaluations) {\n if (!evaluation?.run) {\n logger.error(`Evaluation ${file} does not properly call evaluate()`);\n if (options.failOnError) {\n process.exit(1);\n }\n continue;\n }\n\n if (options.frontendPort) {\n evaluation.setFrontendPort(options.frontendPort);\n }\n const evalResult = await evaluation.run();\n scores.push({\n file,\n scores: evalResult?.averageScores ?? {},\n url: evalResult?.url ?? '',\n evaluationId: evalResult?.evaluationId ?? '',\n });\n }\n }\n\n if (options.outputFile) {\n fs.writeFileSync(options.outputFile, JSON.stringify(scores, null, 2));\n }\n}\n\n","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\n\nimport { version } from \"../../package.json\";\nimport { Evaluation } from \"../evaluations\";\nimport { initializeLogger } from \"../utils\";\nimport {\n handleDatasetsCreate,\n handleDatasetsList,\n handleDatasetsPull,\n handleDatasetsPush,\n} from \"./datasets\";\nimport { runEvaluation } from \"./evals\";\nimport { proxyToLmnrCli } from \"./proxy-to-lmnr-cli.js\";\n\nconst logger = initializeLogger();\n\ndeclare global {\n var _evaluations: Evaluation<any, any, any>[] | undefined;\n var _set_global_evaluation: boolean;\n}\n\nasync function cli() {\n const program = new Command();\n\n program\n .name(\"lmnr\")\n .description(\"CLI for Laminar. Use `lmnr <subcommand> --help` for more information.\")\n .version(version, \"-v, --version\", \"display version number\");\n\n // Eval command\n program\n .command(\"eval\")\n .description(\"Run an evaluation\")\n .argument(\n \"[files...]\",\n \"A file or files containing the evaluation to run. If no file is provided, \" +\n \"the evaluation will run all `*.eval.ts|js` files in the `evals` directory. \" +\n \"If multiple files are provided, the evaluation will run each file in order.\",\n )\n .option(\n \"--fail-on-error\",\n \"Fail on error. If specified, will fail if encounters a file that cannot be run\",\n )\n .option(\n \"--output-file <file>\",\n \"Output file to write the results to. Outputs are written in JSON format.\",\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 eval 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 evaluation itself.\",\n )\n .option(\n \"--frontend-port <port>\",\n \"Port for the Laminar frontend. Defaults to 5667\",\n (val) => parseInt(val, 10),\n )\n .action(async (files: string[], options) => {\n await runEvaluation(files, options);\n });\n\n const deprecatedDatasetsWarning =\n \"DeprecationWarning: `lmnr datasets` is deprecated and will be removed in a future version. \" +\n \"Use `lmnr-cli dataset` instead.\";\n\n // Datasets command with global options\n const datasetCmd = program\n .command(\"datasets\")\n .description(\"[DEPRECATED] Manage datasets. Use `lmnr-cli dataset` instead.\")\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\n // Datasets list command\n datasetCmd\n .command(\"list\")\n .description(\"List all datasets\")\n .action(async (options, cmd) => {\n process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsList({ ...parentOpts, ...options });\n });\n\n // Datasets push command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsPush(paths, { ...parentOpts, ...options });\n });\n\n // Datasets pull command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsPull(outputPath, { ...parentOpts, ...options });\n });\n\n // Datasets create command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsCreate(name, paths, { ...parentOpts, ...options });\n });\n\n // Dev command - proxy to lmnr-cli\n program\n .command(\"dev\")\n .description(\"Start a rollout debugging session\")\n .argument(\"[file]\", \"Path to file containing the agent function(s)\")\n .allowExcessArguments(true)\n .allowUnknownOption(true)\n .action(() => {\n // Find the dev command arguments (everything after 'dev')\n const devIndex = process.argv.indexOf('dev');\n const devArgs = devIndex !== -1 ? process.argv.slice(devIndex + 1) : [];\n\n // Proxy to lmnr-cli with 'dev' command and all arguments\n proxyToLmnrCli(['dev', ...devArgs]);\n });\n\n // If no command provided, show help\n if (!process.argv.slice(2).length) {\n program.help();\n return;\n }\n\n await program.parseAsync();\n}\n\ncli().catch((err) => {\n logger.error(err instanceof Error ? err.message : err);\n throw err;\n});\n\n"],"mappings":";;;;;;;;;;;;;;AAOA,MAAMA,WAASC,cAAAA,kBAAkB;AACjC,MAAM,kCAAkC;AACxC,MAAM,kCAAkC;;;;AAWxC,MAAM,cAAc,OAClB,QACA,YACA,YAAoB,iCACpB,SAAiB,GACjB,UAC+B;CAC/B,IAAI,UAAU;CACd,IAAI,gBAAgB;CACpB,MAAM,SAAS,UAAU,KAAA,IAAY,SAAS,QAAQ,KAAA;CAEtD,MAAM,SAA4B,EAAE;AAEpC,QAAO,YAAY,WAAW,KAAA,KAAa,gBAAgB,SAAS;EAClE,MAAM,OAAO,MAAM,OAAO,SAAS,KAAW;GAC5C,GAAG;GACH,QAAQ;GACR,OAAO;GACR,CAAC;AAEF,SAAO,KAAK,GAAG,KAAK,MAAM;AAG1B,MAAI,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,SAAS,UACjD,WAAU;WACD,WAAW,KAAA,KAAa,gBAAgB,aAAa,OAC9D,WAAU;WACD,KAAK,eAAe,KAAA,KAAa,gBAAgB,aAAa,KAAK,WAC5E,WAAU;AAGZ,mBAAiB;;AAGnB,KAAI,UAAU,KAAA,EACZ,QAAO,OAAO,MAAM,GAAG,MAAM;AAG/B,QAAO;;;;;AAMT,MAAa,qBAAqB,OAChC,YACkB;CAClB,MAAM,SAAS,IAAIC,aAAAA,cAAc;EAC/B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACf,CAAC;AAEF,KAAI;EACF,MAAM,WAAW,MAAM,OAAO,SAAS,cAAc;AAErD,MAAI,SAAS,WAAW,GAAG;AACzB,WAAQ,IAAI,qBAAqB;AACjC;;EAIF,MAAM,UAAU;EAChB,MAAM,iBAAiB;AAEvB,UAAQ,IAAI,KAAK,KAAK,OAAO,QAAQ,CAAC,IAAI,aAAa,OAAO,eAAe,CAAC,QAAQ;AACtF,UAAQ,IAAI,GAAG,IAAI,OAAO,QAAQ,CAAC,IAAI,IAAI,OAAO,eAAe,CAAC,IAAI,IAAI,OAAO,GAAG,GAAG;AAGvF,OAAK,MAAM,WAAW,UAAU;GAE9B,MAAM,eADY,IAAI,KAAK,QAAQ,UAAU,CACd,aAAa,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,GAAG,GAAG;AAC/E,WAAQ,IACN,GAAG,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,aAAa,OAAO,eAAe,CAAC,IAAI,QAAQ,OACnF;;AAGH,UAAQ,IAAI,YAAY,SAAS,OAAO,eAAe;UAChD,OAAO;AACd,WAAO,MACL,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACnF;;;;;;AAOL,MAAa,qBAAqB,OAChC,OACA,YAMkB;AAClB,KAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,IAAI;AAChC,WAAO,MAAM,qCAAqC;AAClD;;AAGF,KAAI,QAAQ,QAAQ,QAAQ,IAAI;AAC9B,WAAO,MAAM,0CAA0C;AACvD;;CAGF,MAAM,SAAS,IAAIA,aAAAA,cAAc;EAC/B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACf,CAAC;CAEF,MAAM,OAAO,MAAMC,mBAAAA,cAAc,OAAO,QAAQ,UAAU;AAE1D,KAAI,KAAK,WAAW,GAAG;AACrB,WAAO,KAAK,4BAA4B;AACxC;;CAGF,MAAM,aAAa,QAAQ,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE,IAAI,QAAQ,IAAI;AAE7E,KAAI;AACF,QAAM,OAAO,SAAS,KAAK;GACzB,QAAQ;GACR,GAAG;GACH,WAAW,QAAQ,aAAa;GACjC,CAAC;AACF,WAAO,KAAK,UAAU,KAAK,OAAO,0BAA0B,QAAQ,QAAQ,QAAQ,KAAK;UAClF,OAAO;AACd,WAAO,MACL,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAClF;;;;;;AAOL,MAAa,qBAAqB,OAChC,YACA,YAQkB;AAClB,KAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,IAAI;AAChC,WAAO,MAAM,qCAAqC;AAClD;;AAGF,KAAI,QAAQ,QAAQ,QAAQ,IAAI;AAC9B,WAAO,MAAM,0CAA0C;AACvD;;CAGF,MAAM,SAAS,IAAID,aAAAA,cAAc;EAC/B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACf,CAAC;CAEF,MAAM,aAAa,QAAQ,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE,IAAI,QAAQ,IAAI;AAE7E,KAAI;EACF,MAAM,SAAS,MAAM,YACnB,QACA,YACA,QAAQ,aAAa,iCACrB,QAAQ,UAAU,GAClB,QAAQ,MACT;AAED,MAAI,YAAY;AACd,SAAME,mBAAAA,YAAY,YAAY,QAAQ,QAAQ,aAAa;AAC3D,YAAO,KAAK,uBAAuB,OAAO,OAAO,kBAAkB,aAAa;QAEhF,oBAAA,eAAe,QAAQ,QAAQ,gBAAgB,OAAO;UAEjD,OAAO;AACd,WAAO,MACL,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAClF;;;;;;AAOL,MAAa,uBAAuB,OAClC,MACA,OACA,YAMkB;CAClB,MAAM,SAAS,IAAIF,aAAAA,cAAc;EAC/B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACf,CAAC;CAGF,MAAM,OAAO,MAAMC,mBAAAA,cAAc,OAAO,QAAQ,UAAU;AAE1D,KAAI,KAAK,WAAW,GAAG;AACrB,WAAO,KAAK,4BAA4B;AACxC;;AAIF,UAAO,KAAK,WAAW,KAAK,OAAO,2BAA2B,KAAK,MAAM;AAEzE,KAAI;AACF,QAAM,OAAO,SAAS,KAAK;GACzB,QAAQ;GACR;GACA,WAAW,QAAQ,aAAa;GAChC,eAAe;GAChB,CAAC;AACF,WAAO,KAAK,uBAAuB,KAAK,OAAO,2BAA2B,KAAK,GAAG;UAC3E,OAAO;AACd,WAAO,MACL,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACpF;AACD;;AAIF,UAAO,KAAK,8BAA8B,KAAK,MAAM;AAErD,KAAI;EACF,MAAM,SAAS,MAAM,YACnB,QACA,EAAE,MAAM,EACR,QAAQ,aAAa,iCACrB,GACA,KAAA,EACD;AAGD,QAAMC,mBAAAA,YAAY,QAAQ,YAAY,QAAQ,QAAQ,aAAa;AAEnE,WAAO,KACL,iCAAiC,KAAK,cACvB,OAAO,OAAO,iBAAiB,QAAQ,aACvD;UACM,OAAO;AACd,WAAO,MACL,0CACK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5D;;;;;AC/QL,MAAMC,WAASC,cAAAA,kBAAkB;AAGjC,MAAM,kCAAkC,iBAA2C;CACjF,MAAM;CACN,MAAM,OAAO;AACX,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG;AAE9C,QAAM,UAAU,EAAE,QAAQ,MAAM,GAAG,SAAS;AAE1C,OAAI,KAAK,SAAS,oBAAoB,YAAY,SAAS,KAAK,KAAK,EAAE;AACrE,aAAO,KAAK,4BAA4B,KAAK,OAAO;AAEpD,WAAO;KACL,MAAM,KAAK;KACX,WAAW;KACZ;;IAEH;AAIF,QAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;GAA4B,GAAG,UAAU;GAC/E,UAAU;GACV,QAAQ;GACT,EAAE;;CAEN;AAED,SAAS,WAAW,EAClB,UACA,cAI8B;AAC9B,YAAW,eAAe,EAAE;AAC5B,YAAW,yBAAyB;CAEpC,MAAM,aAAa;CACnB,MAAM,YAAYC,cAAAA,YAAY;AAK9B,KAAI,SACF,WACA,UACA,cACA,aACA,WACD,CACC,SACA,QACA,YACA,UACD;AAID,QAAO,WAAW;;AAWpB,eAAsB,cACpB,OACA,SACe;CACf,IAAI;AACJ,KAAI,SAAS,MAAM,SAAS,EAC1B,aAAY,MAAM,SAAS,SAAiB,KAAK,KAAK,KAAK,CAAC;KAG5D,aAAY,KAAK,KAAK,0BAA0B;AAGlD,WAAU,MAAM;AAEhB,KAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,MAAM,uKAEoC;AACjD,UAAQ,KAAK,EAAE;;AAGjB,KAAI,MAAM,WAAW,EACnB,UAAO,KAAK,WAAW,UAAU,OAAO,6BAA6B;KAErE,UAAO,KAAK,WAAW,UAAU,OAAO,oBAAoB;CAG9D,MAAM,SAKA,EAAE;AAER,MAAK,MAAM,QAAQ,WAAW;AAC5B,WAAO,KAAK,WAAW,KAAK,KAAK;EACjC,MAAM,eAAe;GACnB,QAAQ;GACR,UAAU;GACV,aAAa,CAAC,KAAK;GACnB,SAAS,WAAW,KAAK;GACzB,OAAO;GACP,UAAU;IACR;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,GAAI,QAAQ,mBAAmB,QAAQ,mBAAmB,EAAE;IAC7D;GACD,SAAS,CACP,+BAA+B,QAAQ,wBAAwB,EAAE,CAAC,CACnE;GACD,aAAa;GACd;EAED,MAAM,SAAS,MAAM,QAAQ,MAAM,aAAa;AAEhD,MAAI,CAAC,OAAO,aAAa;AACvB,YAAO,MAAM,4HACsE;AACnF,OAAI,QAAQ,YACV,SAAQ,KAAK,EAAE;AAEjB;;EAGF,MAAM,iBAAiB,OAAO,YAAY,GAAG;EAE7C,MAAM,cAAc,WAAW;GAC7B,UAAU;GACV,YAAY;GACb,CAAC;AAEF,WAAO,KAAK,UAAU,YAAY,OAAO,oBAAoB,OAAO;AAEpE,OAAK,MAAM,cAAc,aAAa;AACpC,OAAI,CAAC,YAAY,KAAK;AACpB,aAAO,MAAM,cAAc,KAAK,oCAAoC;AACpE,QAAI,QAAQ,YACV,SAAQ,KAAK,EAAE;AAEjB;;AAGF,OAAI,QAAQ,aACV,YAAW,gBAAgB,QAAQ,aAAa;GAElD,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,UAAO,KAAK;IACV;IACA,QAAQ,YAAY,iBAAiB,EAAE;IACvC,KAAK,YAAY,OAAO;IACxB,cAAc,YAAY,gBAAgB;IAC3C,CAAC;;;AAIN,KAAI,QAAQ,WACV,IAAG,cAAc,QAAQ,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;;;;ACtKzE,MAAM,SAASC,cAAAA,kBAAkB;AAOjC,eAAe,MAAM;CACnB,MAAM,UAAU,IAAIC,UAAAA,SAAS;AAE7B,SACG,KAAK,OAAO,CACZ,YAAY,wEAAwE,CACpF,QAAQC,aAAAA,SAAS,iBAAiB,yBAAyB;AAG9D,SACG,QAAQ,OAAO,CACf,YAAY,oBAAoB,CAChC,SACC,cACA,mOAGD,CACA,OACC,mBACA,iFACD,CACA,OACC,wBACA,2EACD,CACA,OACC,qCACA,wNAGD,CACA,OACC,0CACA,8OAGD,CACA,OACC,0BACA,oDACC,QAAQ,SAAS,KAAK,GAAG,CAC3B,CACA,OAAO,OAAO,OAAiB,YAAY;AAC1C,QAAM,cAAc,OAAO,QAAQ;GACnC;CAEJ,MAAM,4BACJ;CAIF,MAAM,aAAa,QAChB,QAAQ,WAAW,CACnB,YAAY,gEAAgE,CAC5E,OACC,2BACA,iFACD,CACA,OACC,oBACA,8FACD,CACA,OACC,iBACA,8CACC,QAAQ,SAAS,KAAK,GAAG,CAC3B;AAGH,YACG,QAAQ,OAAO,CACf,YAAY,oBAAoB,CAChC,OAAO,OAAO,SAAS,QAAQ;AAC9B,UAAQ,OAAO,MAAM,4BAA4B,KAAK;AAEtD,QAAM,mBAAmB;GAAE,GADR,IAAI,QAAQ,MAAM,IAAI,EAAE;GACD,GAAG;GAAS,CAAC;GACvD;AAGJ,YACG,QAAQ,OAAO,CACf,YAAY,yCAAyC,CACrD,SAAS,cAAc,wDAAwD,CAC/E,OAAO,qBAAqB,2DAA2D,CACvF,OAAO,aAAa,yDAAyD,CAC7E,OAAO,mBAAmB,yCAAyC,MAAM,CACzE,OACC,uBACA,gCACC,QAAQ,SAAS,KAAK,GAAG,EAC1B,IACD,CACA,OAAO,OAAO,OAAiB,SAAS,QAAQ;AAC/C,UAAQ,OAAO,MAAM,4BAA4B,KAAK;AAEtD,QAAM,mBAAmB,OAAO;GAAE,GADf,IAAI,QAAQ,MAAM,IAAI,EAAE;GACM,GAAG;GAAS,CAAC;GAC9D;AAGJ,YACG,QAAQ,OAAO,CACf,YAAY,2BAA2B,CACvC,SAAS,iBAAiB,4DAA4D,CACtF,OAAO,qBAAqB,2DAA2D,CACvF,OAAO,aAAa,yDAAyD,CAC7E,OACC,4BACA,iFACD,CACA,OACC,uBACA,gCACC,QAAQ,SAAS,KAAK,GAAG,EAC1B,IACD,CACA,OAAO,mBAAmB,uCAAuC,QAAQ,SAAS,KAAK,GAAG,CAAC,CAC3F,OAAO,qBAAqB,0BAA0B,QAAQ,SAAS,KAAK,GAAG,EAAE,EAAE,CACnF,OAAO,OAAO,YAAgC,SAAS,QAAQ;AAC9D,UAAQ,OAAO,MAAM,4BAA4B,KAAK;AAEtD,QAAM,mBAAmB,YAAY;GAAE,GADpB,IAAI,QAAQ,MAAM,IAAI,EAAE;GACW,GAAG;GAAS,CAAC;GACnE;AAGJ,YACG,QAAQ,SAAS,CACjB,YAAY,oCAAoC,CAChD,SAAS,UAAU,gCAAgC,CACnD,SAAS,cAAc,wDAAwD,CAC/E,eAAe,4BAA4B,+BAA+B,CAC1E,OACC,4BACA,iFACD,CACA,OAAO,mBAAmB,yCAAyC,MAAM,CACzE,OACC,uBACA,wCACC,QAAQ,SAAS,KAAK,GAAG,EAC1B,IACD,CACA,OAAO,OAAO,MAAc,OAAiB,SAAS,QAAQ;AAC7D,UAAQ,OAAO,MAAM,4BAA4B,KAAK;AAEtD,QAAM,qBAAqB,MAAM,OAAO;GAAE,GADvB,IAAI,QAAQ,MAAM,IAAI,EAAE;GACc,GAAG;GAAS,CAAC;GACtE;AAGJ,SACG,QAAQ,MAAM,CACd,YAAY,oCAAoC,CAChD,SAAS,UAAU,gDAAgD,CACnE,qBAAqB,KAAK,CAC1B,mBAAmB,KAAK,CACxB,aAAa;EAEZ,MAAM,WAAW,QAAQ,KAAK,QAAQ,MAAM;AAI5C,4BAAA,eAAe,CAAC,OAAO,GAHP,aAAa,KAAK,QAAQ,KAAK,MAAM,WAAW,EAAE,GAAG,EAAE,CAGrC,CAAC;GACnC;AAGJ,KAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC,QAAQ;AACjC,UAAQ,MAAM;AACd;;AAGF,OAAM,QAAQ,YAAY;;AAG5B,KAAK,CAAC,OAAO,QAAQ;AACnB,QAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,IAAI;AACtD,OAAM;EACN"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["logger","initializeLogger","LaminarClient","errorMessage","loadFromPaths","writeToFile","logger","initializeLogger","getDirname","initializeLogger","Command","version","errorMessage"],"sources":["../src/cli/datasets.ts","../src/cli/evals.ts","../src/cli/index.ts"],"sourcesContent":["import { LaminarClient } from \"@lmnr-ai/client\";\nimport { errorMessage, type StringUUID } from \"@lmnr-ai/types\";\n\nimport { Datapoint } from \"../evaluations\";\nimport { initializeLogger } from \"../utils\";\nimport { loadFromPaths, printToConsole, writeToFile } from \"./file-utils\";\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}\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 (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 logger.error(\n `Failed to list datasets: ${errorMessage(error)}`,\n );\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 logger.error(\"Either name or id must be provided\");\n return;\n }\n\n if (options.name && options.id) {\n logger.error(\"Only one of name or id must be provided\");\n return;\n }\n\n const client = new LaminarClient({\n projectApiKey: options.projectApiKey,\n baseUrl: options.baseUrl,\n port: options.port,\n });\n\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n logger.warn(\"No data to push. Skipping\");\n return;\n }\n\n const identifier = options.name ? { name: options.name } : { id: options.id };\n\n try {\n await client.datasets.push({\n points: data,\n ...identifier,\n batchSize: options.batchSize ?? DEFAULT_DATASET_PUSH_BATCH_SIZE,\n });\n logger.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);\n } catch (error) {\n logger.error(\n `Failed to push dataset: ${errorMessage(error)}`,\n );\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 logger.error(\"Either name or id must be provided\");\n return;\n }\n\n if (options.name && options.id) {\n logger.error(\"Only one of name or id must be provided\");\n return;\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 logger.info(`Successfully pulled ${result.length} data points to ${outputPath}`);\n } else {\n printToConsole(result, options.outputFormat ?? 'json');\n }\n } catch (error) {\n logger.error(\n `Failed to pull dataset: ${errorMessage(error)}`,\n );\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 // Load data from input files\n const data = await loadFromPaths(paths, options.recursive);\n\n if (data.length === 0) {\n logger.warn(\"No data to push. Skipping\");\n return;\n }\n\n // Push data to create/populate the dataset\n logger.info(`Pushing ${data.length} data points to dataset '${name}'...`);\n\n try {\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 logger.error(\n `Failed to create dataset: ${errorMessage(error)}`,\n );\n return;\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 logger.info(\n `Successfully created dataset '${name}' `\n + `and saved ${result.length} datapoints to ${options.outputFile}`,\n );\n } catch (error) {\n logger.error(\n \"Failed to pull dataset after creation: \" + errorMessage(error),\n );\n }\n};\n\n","import * as esbuild from \"esbuild\";\nimport * as fs from \"fs\";\nimport * as glob from \"glob\";\n\nimport { Evaluation } from \"../evaluations\";\nimport { getDirname, initializeLogger } from \"../utils\";\n\nconst logger = initializeLogger();\n\n// esbuild plugin to skip dynamic imports\nconst createSkipDynamicImportsPlugin = (skipModules: string[]): esbuild.Plugin => ({\n name: 'skip-dynamic-imports',\n setup(build) {\n if (!skipModules || skipModules.length === 0) return;\n\n build.onResolve({ filter: /.*/ }, (args) => {\n // Only handle dynamic imports\n if (args.kind === 'dynamic-import' && skipModules.includes(args.path)) {\n logger.warn(`Skipping dynamic import: ${args.path}`);\n // Return a virtual module that exports an empty object\n return {\n path: args.path,\n namespace: 'lmnr-skip-dynamic-import',\n };\n }\n });\n\n // Provide empty module content for skipped dynamic imports\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n build.onLoad({ filter: /.*/, namespace: 'lmnr-skip-dynamic-import' }, (args) => ({\n contents: 'export default {};',\n loader: 'js',\n }));\n },\n});\n\nfunction loadModule({\n filename,\n moduleText,\n}: {\n filename: string;\n moduleText: string;\n}): Evaluation<any, any, any>[] {\n globalThis._evaluations = [];\n globalThis._set_global_evaluation = true;\n\n const __filename = filename;\n const __dirname = getDirname();\n\n // add some arguments for proper cjs/esm interop\n\n /* eslint-disable @typescript-eslint/no-implied-eval */\n new Function(\n \"require\",\n \"module\",\n \"__filename\",\n \"__dirname\",\n moduleText,\n )(\n require,\n module,\n __filename,\n __dirname,\n );\n /* eslint-enable @typescript-eslint/no-implied-eval */\n\n // Return the modified _evals global variable\n return globalThis._evaluations;\n}\n\nexport interface EvalCommandOptions {\n failOnError?: boolean;\n outputFile?: string;\n externalPackages?: string[];\n dynamicImportsToSkip?: string[];\n frontendPort?: number;\n}\n\nexport async function runEvaluation(\n files: string[],\n options: EvalCommandOptions,\n): Promise<void> {\n let evalFiles: string[];\n if (files && files.length > 0) {\n evalFiles = files.flatMap((file: string) => glob.sync(file));\n } else {\n // No files provided, use default pattern\n evalFiles = glob.sync('evals/**/*.eval.{ts,js}');\n }\n\n evalFiles.sort();\n\n if (evalFiles.length === 0) {\n logger.error(\"No evaluation files found. Please provide a file or \" +\n \"ensure there are eval files that are named like `*.eval.{ts,js}` in \" +\n \"the `evals` directory or its subdirectories.\");\n process.exit(1);\n }\n\n if (files.length === 0) {\n logger.info(`Located ${evalFiles.length} evaluation files in evals/`);\n } else {\n logger.info(`Running ${evalFiles.length} evaluation files.`);\n }\n\n const scores: {\n file: string,\n scores: Record<string, number>,\n url: string,\n evaluationId: string,\n }[] = [];\n\n for (const file of evalFiles) {\n logger.info(`Loading ${file}...`);\n const buildOptions = {\n bundle: true,\n platform: \"node\" as esbuild.Platform,\n entryPoints: [file],\n outfile: `tmp_out_${file}.js`,\n write: false, // will be loaded in memory as a temp file\n external: [\n \"@lmnr-ai/lmnr\",\n \"@lmnr-ai/lmnr/*\",\n \"@lmnr-ai/client\",\n \"@lmnr-ai/types\",\n \"esbuild\",\n \"fsevents\",\n \"playwright\",\n \"puppeteer\",\n \"puppeteer-core\",\n \"playwright-core\",\n ...(options.externalPackages ? options.externalPackages : []),\n ],\n plugins: [\n createSkipDynamicImportsPlugin(options.dynamicImportsToSkip || []),\n ],\n treeShaking: true,\n };\n\n const result = await esbuild.build(buildOptions);\n\n if (!result.outputFiles) {\n logger.error(\"Error when building: No output files found \" +\n \"it is likely that all eval files are not valid TypeScript or JavaScript files.\");\n if (options.failOnError) {\n process.exit(1);\n }\n continue;\n }\n\n const outputFileText = result.outputFiles[0].text;\n\n const evaluations = loadModule({\n filename: file,\n moduleText: outputFileText,\n });\n\n logger.info(`Loaded ${evaluations.length} evaluations from ${file}`);\n\n for (const evaluation of evaluations) {\n if (!evaluation?.run) {\n logger.error(`Evaluation ${file} does not properly call evaluate()`);\n if (options.failOnError) {\n process.exit(1);\n }\n continue;\n }\n\n if (options.frontendPort) {\n evaluation.setFrontendPort(options.frontendPort);\n }\n const evalResult = await evaluation.run();\n scores.push({\n file,\n scores: evalResult?.averageScores ?? {},\n url: evalResult?.url ?? '',\n evaluationId: evalResult?.evaluationId ?? '',\n });\n }\n }\n\n if (options.outputFile) {\n fs.writeFileSync(options.outputFile, JSON.stringify(scores, null, 2));\n }\n}\n\n","#!/usr/bin/env node\n\nimport { errorMessage } from \"@lmnr-ai/types\";\nimport { Command } from \"commander\";\n\nimport { version } from \"../../package.json\";\nimport { Evaluation } from \"../evaluations\";\nimport { initializeLogger } from \"../utils\";\nimport {\n handleDatasetsCreate,\n handleDatasetsList,\n handleDatasetsPull,\n handleDatasetsPush,\n} from \"./datasets\";\nimport { runEvaluation } from \"./evals\";\nimport { proxyToLmnrCli } from \"./proxy-to-lmnr-cli.js\";\n\nconst logger = initializeLogger();\n\ndeclare global {\n var _evaluations: Evaluation<any, any, any>[] | undefined;\n var _set_global_evaluation: boolean;\n}\n\nasync function cli() {\n const program = new Command();\n\n program\n .name(\"lmnr\")\n .description(\"CLI for Laminar. Use `lmnr <subcommand> --help` for more information.\")\n .version(version, \"-v, --version\", \"display version number\");\n\n // Eval command\n program\n .command(\"eval\")\n .description(\"Run an evaluation\")\n .argument(\n \"[files...]\",\n \"A file or files containing the evaluation to run. If no file is provided, \" +\n \"the evaluation will run all `*.eval.ts|js` files in the `evals` directory. \" +\n \"If multiple files are provided, the evaluation will run each file in order.\",\n )\n .option(\n \"--fail-on-error\",\n \"Fail on error. If specified, will fail if encounters a file that cannot be run\",\n )\n .option(\n \"--output-file <file>\",\n \"Output file to write the results to. Outputs are written in JSON format.\",\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 eval 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 evaluation itself.\",\n )\n .option(\n \"--frontend-port <port>\",\n \"Port for the Laminar frontend. Defaults to 5667\",\n (val) => parseInt(val, 10),\n )\n .action(async (files: string[], options) => {\n await runEvaluation(files, options);\n });\n\n const deprecatedDatasetsWarning =\n \"DeprecationWarning: `lmnr datasets` is deprecated and will be removed in a future version. \" +\n \"Use `lmnr-cli dataset` instead.\";\n\n // Datasets command with global options\n const datasetCmd = program\n .command(\"datasets\")\n .description(\"[DEPRECATED] Manage datasets. Use `lmnr-cli dataset` instead.\")\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\n // Datasets list command\n datasetCmd\n .command(\"list\")\n .description(\"List all datasets\")\n .action(async (options, cmd) => {\n process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsList({ ...parentOpts, ...options });\n });\n\n // Datasets push command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsPush(paths, { ...parentOpts, ...options });\n });\n\n // Datasets pull command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsPull(outputPath, { ...parentOpts, ...options });\n });\n\n // Datasets create command\n datasetCmd\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 process.stderr.write(deprecatedDatasetsWarning + \"\\n\");\n const parentOpts = cmd.parent?.opts() || {};\n await handleDatasetsCreate(name, paths, { ...parentOpts, ...options });\n });\n\n // Dev command - proxy to lmnr-cli\n program\n .command(\"dev\")\n .description(\"Start a rollout debugging session\")\n .argument(\"[file]\", \"Path to file containing the agent function(s)\")\n .allowExcessArguments(true)\n .allowUnknownOption(true)\n .action(() => {\n // Find the dev command arguments (everything after 'dev')\n const devIndex = process.argv.indexOf('dev');\n const devArgs = devIndex !== -1 ? process.argv.slice(devIndex + 1) : [];\n\n // Proxy to lmnr-cli with 'dev' command and all arguments\n proxyToLmnrCli(['dev', ...devArgs]);\n });\n\n // If no command provided, show help\n if (!process.argv.slice(2).length) {\n program.help();\n return;\n }\n\n await program.parseAsync();\n}\n\ncli().catch((err) => {\n logger.error(errorMessage(err));\n throw err;\n});\n\n"],"mappings":"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"}
|
package/dist/cli.d.cts
CHANGED
package/dist/cli.d.mts
CHANGED
package/dist/cli.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { r as __require } from "./chunk-BEJ448es.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as writeToFile, n as loadFromPaths, r as printToConsole } from "./file-utils-
|
|
3
|
+
import { R as errorMessage, i as getDirname, s as initializeLogger } from "./utils-C6favgeA.mjs";
|
|
4
|
+
import { n as version, t as LaminarClient } from "./dist-CEeuq__5.mjs";
|
|
5
|
+
import { i as writeToFile, n as loadFromPaths, r as printToConsole } from "./file-utils-qcxtoRI-.mjs";
|
|
6
6
|
import { t as proxyToLmnrCli } from "./proxy-to-lmnr-cli-DNDxudgt.mjs";
|
|
7
7
|
import * as fs from "fs";
|
|
8
8
|
import { Command } from "commander";
|
|
@@ -60,7 +60,7 @@ const handleDatasetsList = async (options) => {
|
|
|
60
60
|
}
|
|
61
61
|
console.log(`\nTotal: ${datasets.length} dataset(s)\n`);
|
|
62
62
|
} catch (error) {
|
|
63
|
-
logger$2.error(`Failed to list datasets: ${
|
|
63
|
+
logger$2.error(`Failed to list datasets: ${errorMessage(error)}`);
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
66
|
/**
|
|
@@ -94,7 +94,7 @@ const handleDatasetsPush = async (paths, options) => {
|
|
|
94
94
|
});
|
|
95
95
|
logger$2.info(`Pushed ${data.length} data points to dataset ${options.name || options.id}`);
|
|
96
96
|
} catch (error) {
|
|
97
|
-
logger$2.error(`Failed to push dataset: ${
|
|
97
|
+
logger$2.error(`Failed to push dataset: ${errorMessage(error)}`);
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
100
|
/**
|
|
@@ -122,7 +122,7 @@ const handleDatasetsPull = async (outputPath, options) => {
|
|
|
122
122
|
logger$2.info(`Successfully pulled ${result.length} data points to ${outputPath}`);
|
|
123
123
|
} else printToConsole(result, options.outputFormat ?? "json");
|
|
124
124
|
} catch (error) {
|
|
125
|
-
logger$2.error(`Failed to pull dataset: ${
|
|
125
|
+
logger$2.error(`Failed to pull dataset: ${errorMessage(error)}`);
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
/**
|
|
@@ -149,7 +149,7 @@ const handleDatasetsCreate = async (name, paths, options) => {
|
|
|
149
149
|
});
|
|
150
150
|
logger$2.info(`Successfully pushed ${data.length} data points to dataset '${name}'`);
|
|
151
151
|
} catch (error) {
|
|
152
|
-
logger$2.error(`Failed to create dataset: ${
|
|
152
|
+
logger$2.error(`Failed to create dataset: ${errorMessage(error)}`);
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
155
155
|
logger$2.info(`Pulling data from dataset '${name}'...`);
|
|
@@ -158,7 +158,7 @@ const handleDatasetsCreate = async (name, paths, options) => {
|
|
|
158
158
|
await writeToFile(options.outputFile, result, options.outputFormat);
|
|
159
159
|
logger$2.info(`Successfully created dataset '${name}' and saved ${result.length} datapoints to ${options.outputFile}`);
|
|
160
160
|
} catch (error) {
|
|
161
|
-
logger$2.error(
|
|
161
|
+
logger$2.error("Failed to pull dataset after creation: " + errorMessage(error));
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
164
|
//#endregion
|
|
@@ -310,7 +310,7 @@ async function cli() {
|
|
|
310
310
|
await program.parseAsync();
|
|
311
311
|
}
|
|
312
312
|
cli().catch((err) => {
|
|
313
|
-
logger.error(err
|
|
313
|
+
logger.error(errorMessage(err));
|
|
314
314
|
throw err;
|
|
315
315
|
});
|
|
316
316
|
//#endregion
|