@lmnr-ai/lmnr 0.8.27 → 0.8.28

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.
Files changed (41) hide show
  1. package/dist/chunk-BN4qSVkS.cjs +50 -0
  2. package/dist/cli.cjs +7 -6
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.d.cts +1 -1
  5. package/dist/cli.d.mts +1 -1
  6. package/dist/cli.mjs +3 -3
  7. package/dist/consts-Cx9iKRmq.cjs +23 -0
  8. package/dist/consts-Cx9iKRmq.cjs.map +1 -0
  9. package/dist/consts-ivIFfgfN.mjs +12 -0
  10. package/dist/consts-ivIFfgfN.mjs.map +1 -0
  11. package/dist/{dist-NGq4u898.cjs → dist-BWFjum5L.cjs} +85 -6
  12. package/dist/dist-BWFjum5L.cjs.map +1 -0
  13. package/dist/{dist-xQn-Qurn.mjs → dist-K0otr9Ia.mjs} +82 -4
  14. package/dist/dist-K0otr9Ia.mjs.map +1 -0
  15. package/dist/{evaluations-DaLDCsj5.d.mts → evaluations-Cs-tqViJ.d.mts} +129 -3
  16. package/dist/{evaluations-53vcYI1f.d.cts → evaluations-Db2jWbjf.d.cts} +129 -3
  17. package/dist/{file-utils-g9E9zyDK.mjs → file-utils-CHgYB_Ei.mjs} +2 -2
  18. package/dist/{file-utils-g9E9zyDK.mjs.map → file-utils-CHgYB_Ei.mjs.map} +1 -1
  19. package/dist/{file-utils-D_KglJSl.cjs → file-utils-Cysp1Ym1.cjs} +8 -7
  20. package/dist/{file-utils-D_KglJSl.cjs.map → file-utils-Cysp1Ym1.cjs.map} +1 -1
  21. package/dist/index.cjs +1742 -815
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +209 -2
  24. package/dist/index.d.mts +209 -2
  25. package/dist/index.mjs +1729 -810
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.cjs +8037 -0
  28. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.cjs.map +1 -0
  29. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.d.cts +113173 -0
  30. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.d.mts +113173 -0
  31. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.mjs +8036 -0
  32. package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.mjs.map +1 -0
  33. package/dist/{utils-ZnY1kHzq.mjs → utils-Bdv7YZH7.mjs} +26 -2
  34. package/dist/utils-Bdv7YZH7.mjs.map +1 -0
  35. package/dist/{utils-DyFz8xv4.cjs → utils-C_Pf3r64.cjs} +29 -54
  36. package/dist/utils-C_Pf3r64.cjs.map +1 -0
  37. package/package.json +13 -3
  38. package/dist/dist-NGq4u898.cjs.map +0 -1
  39. package/dist/dist-xQn-Qurn.mjs.map +0 -1
  40. package/dist/utils-DyFz8xv4.cjs.map +0 -1
  41. package/dist/utils-ZnY1kHzq.mjs.map +0 -1
@@ -0,0 +1,50 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ //#endregion
33
+ Object.defineProperty(exports, "__commonJSMin", {
34
+ enumerable: true,
35
+ get: function() {
36
+ return __commonJSMin;
37
+ }
38
+ });
39
+ Object.defineProperty(exports, "__exportAll", {
40
+ enumerable: true,
41
+ get: function() {
42
+ return __exportAll;
43
+ }
44
+ });
45
+ Object.defineProperty(exports, "__toESM", {
46
+ enumerable: true,
47
+ get: function() {
48
+ return __toESM;
49
+ }
50
+ });
package/dist/cli.cjs CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
- const require_utils = require("./utils-DyFz8xv4.cjs");
3
- const require_dist = require("./dist-NGq4u898.cjs");
4
- const require_file_utils = require("./file-utils-D_KglJSl.cjs");
2
+ const require_chunk = require("./chunk-BN4qSVkS.cjs");
3
+ const require_utils = require("./utils-C_Pf3r64.cjs");
4
+ const require_dist = require("./dist-BWFjum5L.cjs");
5
+ const require_file_utils = require("./file-utils-Cysp1Ym1.cjs");
5
6
  let fs = require("fs");
6
- fs = require_utils.__toESM(fs);
7
+ fs = require_chunk.__toESM(fs);
7
8
  let commander = require("commander");
8
9
  let esbuild = require("esbuild");
9
- esbuild = require_utils.__toESM(esbuild);
10
+ esbuild = require_chunk.__toESM(esbuild);
10
11
  let glob = require("glob");
11
- glob = require_utils.__toESM(glob);
12
+ glob = require_chunk.__toESM(glob);
12
13
  //#region src/cli/datasets.ts
13
14
  const logger$2 = require_utils.initializeLogger();
14
15
  const DEFAULT_DATASET_PULL_BATCH_SIZE = 100;
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
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\";\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 // 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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"}
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\";\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 // 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
@@ -1,4 +1,4 @@
1
- import { n as Evaluation } from "./evaluations-53vcYI1f.cjs";
1
+ import { n as Evaluation } from "./evaluations-Db2jWbjf.cjs";
2
2
 
3
3
  //#region src/cli/index.d.ts
4
4
  declare global {
package/dist/cli.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as Evaluation } from "./evaluations-DaLDCsj5.mjs";
1
+ import { n as Evaluation } from "./evaluations-Cs-tqViJ.mjs";
2
2
 
3
3
  //#region src/cli/index.d.ts
4
4
  declare global {
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { r as __require } from "./chunk-hT5z_Zn9.mjs";
3
- import { L as errorMessage, i as getDirname, s as initializeLogger } from "./utils-ZnY1kHzq.mjs";
4
- import { n as version, t as LaminarClient } from "./dist-xQn-Qurn.mjs";
5
- import { i as writeToFile, n as loadFromPaths, r as printToConsole } from "./file-utils-g9E9zyDK.mjs";
3
+ import { L as errorMessage, i as getDirname, s as initializeLogger } from "./utils-Bdv7YZH7.mjs";
4
+ import { n as version, t as LaminarClient } from "./dist-K0otr9Ia.mjs";
5
+ import { i as writeToFile, n as loadFromPaths, r as printToConsole } from "./file-utils-CHgYB_Ei.mjs";
6
6
  import * as fs from "fs";
7
7
  import { Command } from "commander";
8
8
  import * as esbuild from "esbuild";
@@ -0,0 +1,23 @@
1
+ //#region src/opentelemetry-lib/instrumentation/temporal/consts.ts
2
+ /** Header key used to carry the serialized Laminar span context through Temporal. */
3
+ const LAMINAR_SPAN_CONTEXT_HEADER = "x-lmnr-span-context";
4
+ /**
5
+ * W3C traceparent header key — written alongside `laminar-span-context` for
6
+ * interop with non-Laminar clients/workers that understand W3C trace context.
7
+ */
8
+ const TRACEPARENT_HEADER = "traceparent";
9
+ //#endregion
10
+ Object.defineProperty(exports, "LAMINAR_SPAN_CONTEXT_HEADER", {
11
+ enumerable: true,
12
+ get: function() {
13
+ return LAMINAR_SPAN_CONTEXT_HEADER;
14
+ }
15
+ });
16
+ Object.defineProperty(exports, "TRACEPARENT_HEADER", {
17
+ enumerable: true,
18
+ get: function() {
19
+ return TRACEPARENT_HEADER;
20
+ }
21
+ });
22
+
23
+ //# sourceMappingURL=consts-Cx9iKRmq.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts-Cx9iKRmq.cjs","names":[],"sources":["../src/opentelemetry-lib/instrumentation/temporal/consts.ts"],"sourcesContent":["/** Header key used to carry the serialized Laminar span context through Temporal. */\nexport const LAMINAR_SPAN_CONTEXT_HEADER = \"x-lmnr-span-context\";\n\n/**\n * W3C traceparent header key — written alongside `laminar-span-context` for\n * interop with non-Laminar clients/workers that understand W3C trace context.\n */\nexport const TRACEPARENT_HEADER = \"traceparent\";\n"],"mappings":";;AACA,MAAa,8BAA8B;;;;;AAM3C,MAAa,qBAAqB"}
@@ -0,0 +1,12 @@
1
+ //#region src/opentelemetry-lib/instrumentation/temporal/consts.ts
2
+ /** Header key used to carry the serialized Laminar span context through Temporal. */
3
+ const LAMINAR_SPAN_CONTEXT_HEADER = "x-lmnr-span-context";
4
+ /**
5
+ * W3C traceparent header key — written alongside `laminar-span-context` for
6
+ * interop with non-Laminar clients/workers that understand W3C trace context.
7
+ */
8
+ const TRACEPARENT_HEADER = "traceparent";
9
+ //#endregion
10
+ export { TRACEPARENT_HEADER as n, LAMINAR_SPAN_CONTEXT_HEADER as t };
11
+
12
+ //# sourceMappingURL=consts-ivIFfgfN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts-ivIFfgfN.mjs","names":[],"sources":["../src/opentelemetry-lib/instrumentation/temporal/consts.ts"],"sourcesContent":["/** Header key used to carry the serialized Laminar span context through Temporal. */\nexport const LAMINAR_SPAN_CONTEXT_HEADER = \"x-lmnr-span-context\";\n\n/**\n * W3C traceparent header key — written alongside `laminar-span-context` for\n * interop with non-Laminar clients/workers that understand W3C trace context.\n */\nexport const TRACEPARENT_HEADER = \"traceparent\";\n"],"mappings":";;AACA,MAAa,8BAA8B;;;;;AAM3C,MAAa,qBAAqB"}
@@ -1,16 +1,17 @@
1
- const require_utils = require("./utils-DyFz8xv4.cjs");
1
+ const require_chunk = require("./chunk-BN4qSVkS.cjs");
2
+ const require_utils = require("./utils-C_Pf3r64.cjs");
2
3
  let dotenv = require("dotenv");
3
4
  let path = require("path");
4
- path = require_utils.__toESM(path, 1);
5
+ path = require_chunk.__toESM(path, 1);
5
6
  let pino = require("pino");
6
- pino = require_utils.__toESM(pino, 1);
7
+ pino = require_chunk.__toESM(pino, 1);
7
8
  let pino_pretty = require("pino-pretty");
8
9
  let uuid = require("uuid");
9
10
  //#region package.json
10
- var version$1 = "0.8.27";
11
+ var version$1 = "0.8.28";
11
12
  //#endregion
12
13
  //#region ../client/dist/index.mjs
13
- var version = "0.8.27";
14
+ var version = "0.8.28";
14
15
  function getLangVersion() {
15
16
  if (typeof process !== "undefined" && process.versions && process.versions.node) return `node-${process.versions.node}`;
16
17
  if (typeof navigator !== "undefined" && navigator.userAgent) return `browser-${navigator.userAgent}`;
@@ -455,6 +456,26 @@ var EvaluatorsResource = class extends BaseResource {
455
456
  }
456
457
  };
457
458
  const logger$1 = initializeLogger();
459
+ /**
460
+ * Map the opaque HIT `response` payload onto a {@link CachedSpan} the provider
461
+ * wrappers can replay. The server-side shape of `response` is not yet frozen
462
+ * (app-server plan 01 leaves it as a `serde_json::Value`), so this stays
463
+ * deliberately tolerant: the whole payload is serialized into `output` (the only
464
+ * field the AI SDK wrapper's `parseCachedSpan` actually reads, via
465
+ * `JSON.parse`), and a `finishReason` is surfaced into `attributes` when the
466
+ * payload carries one. `name`/`input` are irrelevant to replay and left empty.
467
+ */
468
+ const toCachedSpan = (response) => {
469
+ const output = typeof response === "string" ? response : JSON.stringify(response ?? null);
470
+ const attributes = {};
471
+ if (response !== null && typeof response === "object" && typeof response.finishReason === "string") attributes["ai.response.finishReason"] = response.finishReason;
472
+ return {
473
+ name: "",
474
+ input: "",
475
+ output,
476
+ attributes
477
+ };
478
+ };
458
479
  var RolloutSessionsResource = class extends BaseResource {
459
480
  constructor(baseHttpUrl, projectApiKey) {
460
481
  super(baseHttpUrl, projectApiKey);
@@ -495,6 +516,64 @@ var RolloutSessionsResource = class extends BaseResource {
495
516
  });
496
517
  if (!response.ok) await this.handleError(response);
497
518
  }
519
+ /**
520
+ * Look up the debug-replay cache for a single LLM call (debug-replay v2).
521
+ *
522
+ * The server is keyed by `inputHash` (hex blake3 of the canonicalized,
523
+ * system-stripped input messages). It returns one of three outcomes:
524
+ * - `{ outcome: "hit", response }` — a cached response to replay.
525
+ * - `{ outcome: "miss" }` — no entry; caller latches live mode.
526
+ * - `{ outcome: "live" }` — run this call live (COLD degrade).
527
+ *
528
+ * Error posture: a non-OK response or a transport error degrades to
529
+ * `{ kind: "live" }` for THIS call only — it never throws and never latches
530
+ * the process-wide live flag (only a real MISS does that). This keeps a flaky
531
+ * cache backend from turning a replay into a crash.
532
+ */
533
+ async cache({ sessionId, replayTraceId, cacheUntil, inputHash }) {
534
+ let response;
535
+ try {
536
+ response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/cache`, {
537
+ method: "POST",
538
+ headers: this.headers(),
539
+ body: JSON.stringify({
540
+ replayTraceId,
541
+ cacheUntil,
542
+ inputHash
543
+ })
544
+ });
545
+ } catch (e) {
546
+ logger$1.warn(`Debug cache lookup failed, running live: ${require_utils.errorMessage(e)}`);
547
+ return { kind: "live" };
548
+ }
549
+ if (!response.ok) {
550
+ logger$1.warn(`Debug cache lookup returned ${response.status}, running live`);
551
+ return { kind: "live" };
552
+ }
553
+ let body;
554
+ try {
555
+ body = await response.json();
556
+ } catch (e) {
557
+ logger$1.warn(`Failed to parse debug cache response, running live: ${require_utils.errorMessage(e)}`);
558
+ return { kind: "live" };
559
+ }
560
+ switch (body.outcome) {
561
+ case "hit":
562
+ if (body.response === null || body.response === void 0) {
563
+ logger$1.warn("Debug cache HIT had no response payload, running live");
564
+ return { kind: "live" };
565
+ }
566
+ return {
567
+ kind: "hit",
568
+ cached: toCachedSpan(body.response)
569
+ };
570
+ case "miss": return { kind: "miss" };
571
+ case "live": return { kind: "live" };
572
+ default:
573
+ logger$1.warn(`Unknown debug cache outcome "${body.outcome}", running live`);
574
+ return { kind: "live" };
575
+ }
576
+ }
498
577
  async delete({ sessionId }) {
499
578
  const response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {
500
579
  method: "DELETE",
@@ -708,4 +787,4 @@ Object.defineProperty(exports, "version", {
708
787
  }
709
788
  });
710
789
 
711
- //# sourceMappingURL=dist-NGq4u898.cjs.map
790
+ //# sourceMappingURL=dist-BWFjum5L.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist-BWFjum5L.cjs","names":["errorMessage"],"sources":["../package.json","../../client/dist/index.mjs"],"sourcesContent":["","import { config } from \"dotenv\";\nimport * as path from \"path\";\nimport pino from \"pino\";\nimport { PinoPretty } from \"pino-pretty\";\nimport { v4 } from \"uuid\";\nimport { errorMessage } from \"@lmnr-ai/types\";\n//#region package.json\nvar version = \"0.8.28\";\n//#endregion\n//#region src/version.ts\nfunction getLangVersion() {\n\tif (typeof process !== \"undefined\" && process.versions && process.versions.node) return `node-${process.versions.node}`;\n\tif (typeof navigator !== \"undefined\" && navigator.userAgent) return `browser-${navigator.userAgent}`;\n\treturn null;\n}\n//#endregion\n//#region src/resources/index.ts\nvar BaseResource = class {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tthis.baseHttpUrl = baseHttpUrl;\n\t\tthis.projectApiKey = projectApiKey;\n\t}\n\theaders() {\n\t\treturn {\n\t\t\tAuthorization: `Bearer ${this.projectApiKey}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\"\n\t\t};\n\t}\n\tasync handleError(response) {\n\t\tconst errorMsg = await response.text();\n\t\tthrow new Error(`${response.status} ${errorMsg}`);\n\t}\n};\n//#endregion\n//#region src/resources/browser-events.ts\nvar BrowserEventsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync send({ sessionId, traceId, events }) {\n\t\tconst payload = {\n\t\t\tsessionId,\n\t\t\ttraceId,\n\t\t\tevents,\n\t\t\tsource: getLangVersion() ?? \"javascript\",\n\t\t\tsdkVersion: version\n\t\t};\n\t\tconst jsonString = JSON.stringify(payload);\n\t\tconst compressedStream = new Blob([jsonString], { type: \"application/json\" }).stream().pipeThrough(new CompressionStream(\"gzip\"));\n\t\tconst compressedData = await new Response(compressedStream).arrayBuffer();\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/browser-sessions/events\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t...this.headers(),\n\t\t\t\t\"Content-Encoding\": \"gzip\"\n\t\t\t},\n\t\t\tbody: compressedData\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n//#endregion\n//#region src/utils.ts\nfunction initializeLogger(options) {\n\tconst colorize = options?.colorize ?? true;\n\tconst level = options?.level ?? process.env.LMNR_LOG_LEVEL?.toLowerCase()?.trim() ?? \"info\";\n\treturn pino({ level }, PinoPretty({\n\t\tcolorize,\n\t\tminimumLevel: level\n\t}));\n}\nconst logger$4 = initializeLogger();\nconst isStringUUID = (id) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id);\nconst newUUID = () => {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n\telse return v4();\n};\nconst otelSpanIdToUUID = (spanId) => {\n\tlet id = spanId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 16) logger$4.warn(`Span ID ${spanId} is not 16 hex chars long. This is not a valid OpenTelemetry span ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$4.error(`Span ID ${spanId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.padStart(32, \"0\").replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst otelTraceIdToUUID = (traceId) => {\n\tlet id = traceId.toLowerCase();\n\tif (id.startsWith(\"0x\")) id = id.slice(2);\n\tif (id.length !== 32) logger$4.warn(`Trace ID ${traceId} is not 32 hex chars long. This is not a valid OpenTelemetry trace ID.`);\n\tif (!/^[0-9a-f]+$/.test(id)) {\n\t\tlogger$4.error(`Trace ID ${traceId} is not a valid hex string. Generating a random UUID instead.`);\n\t\treturn newUUID();\n\t}\n\treturn id.replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/, \"$1-$2-$3-$4-$5\");\n};\nconst slicePayload = (value, length) => {\n\tif (value === null || value === void 0) return value;\n\tconst str = JSON.stringify(value);\n\tif (str.length <= length) return value;\n\treturn str.slice(0, length) + \"...\";\n};\nconst loadEnv = (options) => {\n\tconst nodeEnv = process.env.NODE_ENV || \"development\";\n\tconst envDir = process.cwd();\n\tconst envFiles = [\n\t\t\".env\",\n\t\t\".env.local\",\n\t\t`.env.${nodeEnv}`,\n\t\t`.env.${nodeEnv}.local`\n\t];\n\tconst logLevel = process.env.LMNR_LOG_LEVEL ?? \"info\";\n\tconst verbose = [\"debug\", \"trace\"].includes(logLevel.trim().toLowerCase());\n\tconst quiet = options?.quiet ?? !verbose;\n\tconfig({\n\t\tpath: options?.paths ?? envFiles.map((envFile) => path.resolve(envDir, envFile)),\n\t\tquiet\n\t});\n};\n//#endregion\n//#region src/resources/datasets.ts\nconst logger$3 = initializeLogger();\nconst DEFAULT_DATASET_PULL_LIMIT = 100;\nconst DEFAULT_DATASET_PUSH_BATCH_SIZE = 100;\nvar DatasetsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* List all datasets.\n\t*\n\t* @returns {Promise<Dataset[]>} Array of datasets\n\t*/\n\tasync listDatasets() {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/datasets\", {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Get a dataset by name.\n\t*\n\t* @param {string} name - Name of the dataset\n\t* @returns {Promise<Dataset[]>} Array of datasets with matching name\n\t*/\n\tasync getDatasetByName(name) {\n\t\tconst params = new URLSearchParams({ name });\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Push datapoints to a dataset.\n\t*\n\t* @param {Object} options - Push options\n\t* @param {Datapoint<D, T>[]} options.points - Datapoints to push\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.batchSize] - Batch size for pushing (default: 100)\n\t* @param {boolean} [options.createDataset] - Whether to create the dataset if it doesn't exist\n\t* @returns {Promise<PushDatapointsResponse | undefined>}\n\t*/\n\tasync push({ points, name, id, batchSize = DEFAULT_DATASET_PUSH_BATCH_SIZE, createDataset = false }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tif (createDataset && !name) throw new Error(\"Name must be provided when creating a new dataset\");\n\t\tconst identifier = name ? { name } : { datasetId: id };\n\t\tconst totalBatches = Math.ceil(points.length / batchSize);\n\t\tlet response;\n\t\tfor (let i = 0; i < points.length; i += batchSize) {\n\t\t\tconst batchNum = Math.floor(i / batchSize) + 1;\n\t\t\tlogger$3.debug(`Pushing batch ${batchNum} of ${totalBatches}`);\n\t\t\tconst batch = points.slice(i, i + batchSize);\n\t\t\tconst fetchResponse = await fetch(this.baseHttpUrl + \"/v1/datasets/datapoints\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t...identifier,\n\t\t\t\t\tdatapoints: batch.map((point) => ({\n\t\t\t\t\t\tdata: point.data,\n\t\t\t\t\t\ttarget: point.target ?? {},\n\t\t\t\t\t\tmetadata: point.metadata ?? {}\n\t\t\t\t\t})),\n\t\t\t\t\tcreateDataset\n\t\t\t\t})\n\t\t\t});\n\t\t\tif (fetchResponse.status !== 200 && fetchResponse.status !== 201) await this.handleError(fetchResponse);\n\t\t\tresponse = await fetchResponse.json();\n\t\t}\n\t\treturn response;\n\t}\n\t/**\n\t* Pull datapoints from a dataset.\n\t*\n\t* @param {Object} options - Pull options\n\t* @param {string} [options.name] - Name of the dataset (either name or id must be provided)\n\t* @param {StringUUID} [options.id] - ID of the dataset (either name or id must be provided)\n\t* @param {number} [options.limit] - Maximum number of datapoints to return (default: 100)\n\t* @param {number} [options.offset] - Offset for pagination (default: 0)\n\t* @returns {Promise<GetDatapointsResponse<D, T>>}\n\t*/\n\tasync pull({ name, id, limit = DEFAULT_DATASET_PULL_LIMIT, offset = 0 }) {\n\t\tif (!name && !id) throw new Error(\"Either name or id must be provided\");\n\t\tif (name && id) throw new Error(\"Only one of name or id must be provided\");\n\t\tconst paramsObj = {\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t};\n\t\tif (name) paramsObj.name = name;\n\t\telse paramsObj.datasetId = id;\n\t\tconst params = new URLSearchParams(paramsObj);\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n//#endregion\n//#region src/resources/evals.ts\nconst logger$2 = initializeLogger();\nconst INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH = 16e6;\nvar EvalsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Initialize an evaluation.\n\t*\n\t* @param {string} name - Name of the evaluation\n\t* @param {string} groupName - Group name of the evaluation\n\t* @param {Record<string, any>} metadata - Optional metadata\n\t* @returns {Promise<InitEvaluationResponse>} Response from the evaluation initialization\n\t*/\n\tasync init(name, groupName, metadata) {\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evals\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname: name ?? null,\n\t\t\t\tgroupName: groupName ?? null,\n\t\t\t\tmetadata: metadata ?? null\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t*\n\t* @param {string} [name] - Optional name of the evaluation\n\t* @param {string} [groupName] - An identifier to group evaluations\n\t* @param {Record<string, any>} [metadata] - Optional metadata\n\t* @returns {Promise<StringUUID>} The evaluation ID\n\t*/\n\tasync create(args) {\n\t\treturn (await this.init(args?.name, args?.groupName, args?.metadata)).id;\n\t}\n\t/**\n\t* Create a new evaluation and return its ID.\n\t* @deprecated use `create` instead.\n\t*/\n\tasync createEvaluation(name, groupName, metadata) {\n\t\treturn (await this.init(name, groupName, metadata)).id;\n\t}\n\t/**\n\t* Create a datapoint for an evaluation.\n\t*\n\t* @param {Object} options - Create datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {D} options.data - The input data for the executor\n\t* @param {T} [options.target] - The target/expected output for evaluators\n\t* @param {Record<string, any>} [options.metadata] - Optional metadata\n\t* @param {number} [options.index] - Optional index of the datapoint\n\t* @param {string} [options.traceId] - Optional trace ID\n\t* @returns {Promise<StringUUID>} The datapoint ID\n\t*/\n\tasync createDatapoint({ evalId, data, target, metadata, index, traceId }) {\n\t\tconst datapointId = newUUID();\n\t\tconst partialDatapoint = {\n\t\t\tid: datapointId,\n\t\t\tdata,\n\t\t\ttarget,\n\t\t\tindex: index ?? 0,\n\t\t\ttraceId: traceId ?? newUUID(),\n\t\t\texecutorSpanId: newUUID(),\n\t\t\tmetadata\n\t\t};\n\t\tawait this.saveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints: [partialDatapoint]\n\t\t});\n\t\treturn datapointId;\n\t}\n\t/**\n\t* Update a datapoint with evaluation results.\n\t*\n\t* @param {Object} options - Update datapoint options\n\t* @param {string} options.evalId - The evaluation ID\n\t* @param {string} options.datapointId - The datapoint ID\n\t* @param {Record<string, number>} options.scores - The scores\n\t* @param {O} [options.executorOutput] - The executor output\n\t* @returns {Promise<void>}\n\t*/\n\tasync updateDatapoint({ evalId, datapointId, scores, executorOutput }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints/${datapointId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\texecutorOutput,\n\t\t\t\tscores\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Save evaluation datapoints.\n\t*\n\t* @param {Object} options - Save datapoints options\n\t* @param {string} options.evalId - ID of the evaluation\n\t* @param {EvaluationDatapoint<D, T, O>[]} options.datapoints - Datapoint to add\n\t* @param {string} [options.groupName] - Group name of the evaluation\n\t* @returns {Promise<void>} Response from the datapoint addition\n\t*/\n\tasync saveDatapoints({ evalId, datapoints, groupName }) {\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t...d,\n\t\t\t\t\tdata: slicePayload(d.data, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\ttarget: slicePayload(d.target, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH),\n\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH)\n\t\t\t\t})),\n\t\t\t\tgroupName: groupName ?? null\n\t\t\t})\n\t\t});\n\t\tif (response.status === 413) return await this.retrySaveDatapoints({\n\t\t\tevalId,\n\t\t\tdatapoints,\n\t\t\tgroupName\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Get evaluation datapoints.\n\t*\n\t* @deprecated Use `client.datasets.pull()` instead.\n\t* @param {Object} options - Get datapoints options\n\t* @param {string} options.datasetName - Name of the dataset\n\t* @param {number} options.offset - Offset at which to start the query\n\t* @param {number} options.limit - Maximum number of datapoints to return\n\t* @returns {Promise<GetDatapointsResponse>} Response from the datapoint retrieval\n\t*/\n\tasync getDatapoints({ datasetName, offset, limit }) {\n\t\tlogger$2.warn(\"evals.getDatapoints() is deprecated. Use client.datasets.pull() instead.\");\n\t\tconst params = new URLSearchParams({\n\t\t\tname: datasetName,\n\t\t\toffset: offset.toString(),\n\t\t\tlimit: limit.toString()\n\t\t});\n\t\tconst response = await fetch(this.baseHttpUrl + `/v1/datasets/datapoints?${params.toString()}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn await response.json();\n\t}\n\tasync retrySaveDatapoints({ evalId, datapoints, groupName, maxRetries = 25, initialLength = INITIAL_EVALUATION_DATAPOINT_MAX_DATA_LENGTH }) {\n\t\tlet length = initialLength;\n\t\tlet lastResponse = null;\n\t\tfor (let i = 0; i < maxRetries; i++) {\n\t\t\tlogger$2.debug(`Retrying save datapoints... ${i + 1} of ${maxRetries}, length: ${length}`);\n\t\t\tconst response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tpoints: datapoints.map((d) => ({\n\t\t\t\t\t\t...d,\n\t\t\t\t\t\tdata: slicePayload(d.data, length),\n\t\t\t\t\t\ttarget: slicePayload(d.target, length),\n\t\t\t\t\t\texecutorOutput: slicePayload(d.executorOutput, length)\n\t\t\t\t\t})),\n\t\t\t\t\tgroupName: groupName ?? null\n\t\t\t\t})\n\t\t\t});\n\t\t\tlastResponse = response;\n\t\t\tlength = Math.floor(length / 2);\n\t\t\tif (response.status !== 413) break;\n\t\t}\n\t\tif (lastResponse && !lastResponse.ok) await this.handleError(lastResponse);\n\t}\n};\n//#endregion\n//#region src/resources/evaluators.ts\n/**\n* Resource for creating evaluator scores\n*/\nvar EvaluatorsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Create a score for a span or trace\n\t*\n\t* @param {ScoreOptions} options - Score creation options\n\t* @param {string} options.name - Name of the score\n\t* @param {string} [options.traceId] - The trace ID to score (will be attached to top-level span)\n\t* @param {string} [options.spanId] - The span ID to score\n\t* @param {Record<string, any>} [options.metadata] - Additional metadata\n\t* @param {number} options.score - The score value (float)\n\t* @returns {Promise<void>}\n\t*\n\t* @example\n\t* // Score by trace ID (will attach to root span)\n\t* await evaluators.score({\n\t* name: \"quality\",\n\t* traceId: \"trace-id-here\",\n\t* score: 0.95,\n\t* metadata: { model: \"gpt-4\" }\n\t* });\n\t*\n\t* @example\n\t* // Score by span ID\n\t* await evaluators.score({\n\t* name: \"relevance\",\n\t* spanId: \"span-id-here\",\n\t* score: 0.87\n\t* });\n\t*/\n\tasync score(options) {\n\t\tconst { name, metadata, score } = options;\n\t\tlet payload;\n\t\tif (\"traceId\" in options && options.traceId) payload = {\n\t\t\tname,\n\t\t\tmetadata,\n\t\t\tscore,\n\t\t\tsource: \"Code\",\n\t\t\ttraceId: isStringUUID(options.traceId) ? options.traceId : otelTraceIdToUUID(options.traceId)\n\t\t};\n\t\telse if (\"spanId\" in options && options.spanId) payload = {\n\t\t\tname,\n\t\t\tmetadata,\n\t\t\tscore,\n\t\t\tsource: \"Code\",\n\t\t\tspanId: isStringUUID(options.spanId) ? options.spanId : otelSpanIdToUUID(options.spanId)\n\t\t};\n\t\telse throw new Error(\"Either 'traceId' or 'spanId' must be provided.\");\n\t\tconst response = await fetch(this.baseHttpUrl + \"/v1/evaluators/score\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n//#endregion\n//#region src/resources/rollout-sessions.ts\nconst logger$1 = initializeLogger();\n/**\n* Map the opaque HIT `response` payload onto a {@link CachedSpan} the provider\n* wrappers can replay. The server-side shape of `response` is not yet frozen\n* (app-server plan 01 leaves it as a `serde_json::Value`), so this stays\n* deliberately tolerant: the whole payload is serialized into `output` (the only\n* field the AI SDK wrapper's `parseCachedSpan` actually reads, via\n* `JSON.parse`), and a `finishReason` is surfaced into `attributes` when the\n* payload carries one. `name`/`input` are irrelevant to replay and left empty.\n*/\nconst toCachedSpan = (response) => {\n\tconst output = typeof response === \"string\" ? response : JSON.stringify(response ?? null);\n\tconst attributes = {};\n\tif (response !== null && typeof response === \"object\" && typeof response.finishReason === \"string\") attributes[\"ai.response.finishReason\"] = response.finishReason;\n\treturn {\n\t\tname: \"\",\n\t\tinput: \"\",\n\t\toutput,\n\t\tattributes\n\t};\n};\nvar RolloutSessionsResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Idempotently register (upsert) a debug session on the backend, keyed on the\n\t* SDK-supplied session id. The backend stores the row so the session is\n\t* visible in the UI; a null/omitted name never clobbers a name set elsewhere.\n\t*\n\t* Returns the backend-resolved `projectId` (derived from the API key) so the\n\t* caller can build the debugger URL; null if the body can't be parsed.\n\t*/\n\tasync register({ sessionId, name }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({ name })\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\ttry {\n\t\t\treturn (await response.json()).projectId ?? null;\n\t\t} catch (e) {\n\t\t\tlogger$1.warn(`Failed to parse rollout register response: ${errorMessage(e)}`);\n\t\t\treturn null;\n\t\t}\n\t}\n\t/**\n\t* Rename an existing debug session. Update-only: the backend returns 404 (and\n\t* this throws) when the session id is unknown for the project, so a mistyped\n\t* id surfaces as an error rather than silently creating a session. Creation\n\t* stays the SDK's job via {@link register}.\n\t*/\n\tasync setName({ sessionId, name }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/name`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({ name })\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n\t/**\n\t* Look up the debug-replay cache for a single LLM call (debug-replay v2).\n\t*\n\t* The server is keyed by `inputHash` (hex blake3 of the canonicalized,\n\t* system-stripped input messages). It returns one of three outcomes:\n\t* - `{ outcome: \"hit\", response }` — a cached response to replay.\n\t* - `{ outcome: \"miss\" }` — no entry; caller latches live mode.\n\t* - `{ outcome: \"live\" }` — run this call live (COLD degrade).\n\t*\n\t* Error posture: a non-OK response or a transport error degrades to\n\t* `{ kind: \"live\" }` for THIS call only — it never throws and never latches\n\t* the process-wide live flag (only a real MISS does that). This keeps a flaky\n\t* cache backend from turning a replay into a crash.\n\t*/\n\tasync cache({ sessionId, replayTraceId, cacheUntil, inputHash }) {\n\t\tlet response;\n\t\ttry {\n\t\t\tresponse = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/cache`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: this.headers(),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\treplayTraceId,\n\t\t\t\t\tcacheUntil,\n\t\t\t\t\tinputHash\n\t\t\t\t})\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tlogger$1.warn(`Debug cache lookup failed, running live: ${errorMessage(e)}`);\n\t\t\treturn { kind: \"live\" };\n\t\t}\n\t\tif (!response.ok) {\n\t\t\tlogger$1.warn(`Debug cache lookup returned ${response.status}, running live`);\n\t\t\treturn { kind: \"live\" };\n\t\t}\n\t\tlet body;\n\t\ttry {\n\t\t\tbody = await response.json();\n\t\t} catch (e) {\n\t\t\tlogger$1.warn(`Failed to parse debug cache response, running live: ${errorMessage(e)}`);\n\t\t\treturn { kind: \"live\" };\n\t\t}\n\t\tswitch (body.outcome) {\n\t\t\tcase \"hit\":\n\t\t\t\tif (body.response === null || body.response === void 0) {\n\t\t\t\t\tlogger$1.warn(\"Debug cache HIT had no response payload, running live\");\n\t\t\t\t\treturn { kind: \"live\" };\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"hit\",\n\t\t\t\t\tcached: toCachedSpan(body.response)\n\t\t\t\t};\n\t\t\tcase \"miss\": return { kind: \"miss\" };\n\t\t\tcase \"live\": return { kind: \"live\" };\n\t\t\tdefault:\n\t\t\t\tlogger$1.warn(`Unknown debug cache outcome \"${body.outcome}\", running live`);\n\t\t\t\treturn { kind: \"live\" };\n\t\t}\n\t}\n\tasync delete({ sessionId }) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\theaders: this.headers()\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n//#endregion\n//#region src/resources/sql.ts\nvar SqlResource = class extends BaseResource {\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\tasync query(sql, parameters = {}) {\n\t\tconst response = await fetch(`${this.baseHttpUrl}/v1/sql/query`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { ...this.headers() },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tquery: sql,\n\t\t\t\tparameters\n\t\t\t})\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn (await response.json()).data;\n\t}\n};\n//#endregion\n//#region src/resources/tags.ts\n/** Resource for tagging traces. */\nvar TagsResource = class extends BaseResource {\n\t/** Resource for tagging traces. */\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Tag a trace with a list of tags. Note that the trace must be ended before\n\t* tagging it. You may want to call `await Laminar.flush()` after the trace\n\t* that you want to tag.\n\t*\n\t* @param {string | StringUUID} trace_id - The trace id to tag.\n\t* @param {string[] | string} tags - The tag or list of tags to add to the trace.\n\t* @returns {Promise<any>} The response from the server.\n\t* @example\n\t* ```javascript\n\t* import { Laminar, observe, LaminarClient } from \"@lmnr-ai/lmnr\";\n\t* Laminar.initialize();\n\t* const client = new LaminarClient();\n\t* let traceId: StringUUID | null = null;\n\t* // Make sure this is called outside of traced context.\n\t* await observe(\n\t* {\n\t* name: \"my-trace\",\n\t* },\n\t* async () => {\n\t* traceId = await Laminar.getTraceId();\n\t* await foo();\n\t* },\n\t* );\n\t*\n\t* // or make sure the trace is ended by this point.\n\t* await Laminar.flush();\n\t* if (traceId) {\n\t* await client.tags.tag(traceId, [\"tag1\", \"tag2\"]);\n\t* }\n\t* ```\n\t*/\n\tasync tag(trace_id, tags) {\n\t\tconst traceTags = Array.isArray(tags) ? tags : [tags];\n\t\tconst formattedTraceId = isStringUUID(trace_id) ? trace_id : otelTraceIdToUUID(trace_id);\n\t\tconst url = this.baseHttpUrl + \"/v1/tag\";\n\t\tconst payload = {\n\t\t\t\"traceId\": formattedTraceId,\n\t\t\t\"names\": traceTags\n\t\t};\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t\tif (!response.ok) await this.handleError(response);\n\t\treturn response.json();\n\t}\n};\n//#endregion\n//#region src/resources/traces.ts\n/** Resource for post-factum operations on existing traces. */\nconst logger = initializeLogger();\nvar TracesResource = class extends BaseResource {\n\t/** Resource for post-factum operations on existing traces. */\n\tconstructor(baseHttpUrl, projectApiKey) {\n\t\tsuper(baseHttpUrl, projectApiKey);\n\t}\n\t/**\n\t* Push a metadata patch to an existing trace.\n\t*\n\t* The patch is shallow-merged server-side into the trace's existing metadata\n\t* (`existing || patch`, last-write-wins per top-level key). Useful for\n\t* attaching post-factum signals — quality scores, human edits, triage labels —\n\t* to a trace that has already finished. The patch does NOT extend `endTime`\n\t* or change tokens / cost / top span / tags / span names. `numSpans` is\n\t* incremented by 1 (paid by the virtual span that carried the patch through\n\t* the ingestion queue) so the new ClickHouse row beats the prior version on\n\t* `ReplacingMergeTree(numSpans)`. No row is added to the `spans` table.\n\t*\n\t* Compared to `Laminar.setTraceMetadata` (which sets metadata on the\n\t* currently in-flight trace via OpenTelemetry attributes), this method\n\t* operates on a finished trace by trace id, so it must be called after the\n\t* trace has been flushed.\n\t*\n\t* A 404 response (the trace was not found in the project — typically because\n\t* it has not been flushed yet) is logged as a warning and the call returns\n\t* without throwing, since the 404 may be expected when pushing too soon\n\t* after the trace run. Pass `failOnNotFound: true` to throw instead (e.g.\n\t* CLI callers that must report the failure). Any other non-OK status throws.\n\t*\n\t* @param traceId - The trace id to push metadata to. Accepts a UUID string\n\t* or a 32-char OTel hex trace id.\n\t* @param metadata - The metadata patch. Top-level keys are merged into the\n\t* trace's existing metadata. Must be non-empty (the server rejects empty\n\t* patches with 400).\n\t* @param options - `failOnNotFound`: throw on 404 instead of warn-and-return.\n\t* @example\n\t* ```typescript\n\t* import { Laminar, observe, LaminarClient } from \"@lmnr-ai/lmnr\";\n\t* Laminar.initialize();\n\t* const client = new LaminarClient();\n\t*\n\t* let traceId: string | null = null;\n\t* await observe({ name: \"generate\" }, async () => {\n\t* traceId = await Laminar.getTraceId();\n\t* });\n\t* await Laminar.flush();\n\t*\n\t* if (traceId) {\n\t* await client.traces.pushMetadata(traceId, {\n\t* score: 0.85,\n\t* reviewer: \"alice\",\n\t* needsReview: false,\n\t* });\n\t* }\n\t* ```\n\t*/\n\tasync pushMetadata(traceId, metadata, options) {\n\t\tif (!metadata || Object.keys(metadata).length === 0) throw new Error(\"metadata must be a non-empty object\");\n\t\tconst formattedTraceId = isStringUUID(traceId) ? traceId : otelTraceIdToUUID(traceId);\n\t\tconst url = this.baseHttpUrl + \"/v1/traces/metadata\";\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: this.headers(),\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttraceId: formattedTraceId,\n\t\t\t\tmetadata\n\t\t\t})\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\tconst message = `Trace ${formattedTraceId} not found. The trace may not have been flushed yet — call await Laminar.flush() and retry.`;\n\t\t\tif (options?.failOnNotFound) throw new Error(message);\n\t\t\tlogger.warn(message);\n\t\t\treturn;\n\t\t}\n\t\tif (!response.ok) await this.handleError(response);\n\t}\n};\n//#endregion\n//#region src/index.ts\nvar LaminarClient = class {\n\tconstructor({ baseUrl, projectApiKey, port } = {}) {\n\t\tloadEnv();\n\t\tthis.projectApiKey = projectApiKey ?? process.env.LMNR_PROJECT_API_KEY;\n\t\tconst httpPort = port ?? (baseUrl?.match(/:\\d{1,5}$/g) ? parseInt(baseUrl.match(/:\\d{1,5}$/g)[0].slice(1)) : 443);\n\t\tconst baseUrlNoPort = (baseUrl ?? process.env.LMNR_BASE_URL)?.replace(/\\/$/, \"\").replace(/:\\d{1,5}$/g, \"\");\n\t\tthis.baseUrl = `${baseUrlNoPort ?? \"https://api.lmnr.ai\"}:${httpPort}`;\n\t\tthis._browserEvents = new BrowserEventsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._datasets = new DatasetsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evals = new EvalsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._evaluators = new EvaluatorsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._rolloutSessions = new RolloutSessionsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._sql = new SqlResource(this.baseUrl, this.projectApiKey);\n\t\tthis._tags = new TagsResource(this.baseUrl, this.projectApiKey);\n\t\tthis._traces = new TracesResource(this.baseUrl, this.projectApiKey);\n\t}\n\tget browserEvents() {\n\t\treturn this._browserEvents;\n\t}\n\tget datasets() {\n\t\treturn this._datasets;\n\t}\n\tget evals() {\n\t\treturn this._evals;\n\t}\n\tget evaluators() {\n\t\treturn this._evaluators;\n\t}\n\tget rolloutSessions() {\n\t\treturn this._rolloutSessions;\n\t}\n\tget sql() {\n\t\treturn this._sql;\n\t}\n\tget tags() {\n\t\treturn this._tags;\n\t}\n\tget traces() {\n\t\treturn this._traces;\n\t}\n};\n//#endregion\nexport { LaminarClient, RolloutSessionsResource };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
- import { L as errorMessage } from "./utils-ZnY1kHzq.mjs";
1
+ import { L as errorMessage } from "./utils-Bdv7YZH7.mjs";
2
2
  import { config } from "dotenv";
3
3
  import * as path from "path";
4
4
  import pino from "pino";
5
5
  import { PinoPretty } from "pino-pretty";
6
6
  import { v4 } from "uuid";
7
7
  //#region package.json
8
- var version$1 = "0.8.27";
8
+ var version$1 = "0.8.28";
9
9
  //#endregion
10
10
  //#region ../client/dist/index.mjs
11
- var version = "0.8.27";
11
+ var version = "0.8.28";
12
12
  function getLangVersion() {
13
13
  if (typeof process !== "undefined" && process.versions && process.versions.node) return `node-${process.versions.node}`;
14
14
  if (typeof navigator !== "undefined" && navigator.userAgent) return `browser-${navigator.userAgent}`;
@@ -453,6 +453,26 @@ var EvaluatorsResource = class extends BaseResource {
453
453
  }
454
454
  };
455
455
  const logger$1 = initializeLogger();
456
+ /**
457
+ * Map the opaque HIT `response` payload onto a {@link CachedSpan} the provider
458
+ * wrappers can replay. The server-side shape of `response` is not yet frozen
459
+ * (app-server plan 01 leaves it as a `serde_json::Value`), so this stays
460
+ * deliberately tolerant: the whole payload is serialized into `output` (the only
461
+ * field the AI SDK wrapper's `parseCachedSpan` actually reads, via
462
+ * `JSON.parse`), and a `finishReason` is surfaced into `attributes` when the
463
+ * payload carries one. `name`/`input` are irrelevant to replay and left empty.
464
+ */
465
+ const toCachedSpan = (response) => {
466
+ const output = typeof response === "string" ? response : JSON.stringify(response ?? null);
467
+ const attributes = {};
468
+ if (response !== null && typeof response === "object" && typeof response.finishReason === "string") attributes["ai.response.finishReason"] = response.finishReason;
469
+ return {
470
+ name: "",
471
+ input: "",
472
+ output,
473
+ attributes
474
+ };
475
+ };
456
476
  var RolloutSessionsResource = class extends BaseResource {
457
477
  constructor(baseHttpUrl, projectApiKey) {
458
478
  super(baseHttpUrl, projectApiKey);
@@ -493,6 +513,64 @@ var RolloutSessionsResource = class extends BaseResource {
493
513
  });
494
514
  if (!response.ok) await this.handleError(response);
495
515
  }
516
+ /**
517
+ * Look up the debug-replay cache for a single LLM call (debug-replay v2).
518
+ *
519
+ * The server is keyed by `inputHash` (hex blake3 of the canonicalized,
520
+ * system-stripped input messages). It returns one of three outcomes:
521
+ * - `{ outcome: "hit", response }` — a cached response to replay.
522
+ * - `{ outcome: "miss" }` — no entry; caller latches live mode.
523
+ * - `{ outcome: "live" }` — run this call live (COLD degrade).
524
+ *
525
+ * Error posture: a non-OK response or a transport error degrades to
526
+ * `{ kind: "live" }` for THIS call only — it never throws and never latches
527
+ * the process-wide live flag (only a real MISS does that). This keeps a flaky
528
+ * cache backend from turning a replay into a crash.
529
+ */
530
+ async cache({ sessionId, replayTraceId, cacheUntil, inputHash }) {
531
+ let response;
532
+ try {
533
+ response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}/cache`, {
534
+ method: "POST",
535
+ headers: this.headers(),
536
+ body: JSON.stringify({
537
+ replayTraceId,
538
+ cacheUntil,
539
+ inputHash
540
+ })
541
+ });
542
+ } catch (e) {
543
+ logger$1.warn(`Debug cache lookup failed, running live: ${errorMessage(e)}`);
544
+ return { kind: "live" };
545
+ }
546
+ if (!response.ok) {
547
+ logger$1.warn(`Debug cache lookup returned ${response.status}, running live`);
548
+ return { kind: "live" };
549
+ }
550
+ let body;
551
+ try {
552
+ body = await response.json();
553
+ } catch (e) {
554
+ logger$1.warn(`Failed to parse debug cache response, running live: ${errorMessage(e)}`);
555
+ return { kind: "live" };
556
+ }
557
+ switch (body.outcome) {
558
+ case "hit":
559
+ if (body.response === null || body.response === void 0) {
560
+ logger$1.warn("Debug cache HIT had no response payload, running live");
561
+ return { kind: "live" };
562
+ }
563
+ return {
564
+ kind: "hit",
565
+ cached: toCachedSpan(body.response)
566
+ };
567
+ case "miss": return { kind: "miss" };
568
+ case "live": return { kind: "live" };
569
+ default:
570
+ logger$1.warn(`Unknown debug cache outcome "${body.outcome}", running live`);
571
+ return { kind: "live" };
572
+ }
573
+ }
496
574
  async delete({ sessionId }) {
497
575
  const response = await fetch(`${this.baseHttpUrl}/v1/rollouts/${sessionId}`, {
498
576
  method: "DELETE",
@@ -695,4 +773,4 @@ var LaminarClient = class {
695
773
  //#endregion
696
774
  export { version$1 as n, LaminarClient as t };
697
775
 
698
- //# sourceMappingURL=dist-xQn-Qurn.mjs.map
776
+ //# sourceMappingURL=dist-K0otr9Ia.mjs.map