langsmith 0.1.21 → 0.1.23-rc.0

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.
@@ -1,2 +1,88 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runEvaluator = exports.DynamicRunEvaluator = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const traceable_js_1 = require("../traceable.cjs");
6
+ /**
7
+ * Wraps an evaluator function + implements the RunEvaluator interface.
8
+ */
9
+ class DynamicRunEvaluator {
10
+ constructor(evaluator) {
11
+ Object.defineProperty(this, "func", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ const wrappedFunc = (input) => {
18
+ const runAndExample = input.langSmithRunAndExample;
19
+ return evaluator(...Object.values(runAndExample));
20
+ };
21
+ this.func = wrappedFunc;
22
+ }
23
+ coerceEvaluationResults(results, sourceRunId) {
24
+ if ("results" in results) {
25
+ throw new Error("EvaluationResults not supported yet.");
26
+ }
27
+ return this.coerceEvaluationResult(results, sourceRunId, true);
28
+ }
29
+ coerceEvaluationResult(result, sourceRunId, allowNoKey = false) {
30
+ if ("key" in result) {
31
+ if (!result.sourceRunId) {
32
+ result.sourceRunId = sourceRunId;
33
+ }
34
+ return result;
35
+ }
36
+ if (!("key" in result)) {
37
+ if (allowNoKey) {
38
+ result["key"] = this.func.name;
39
+ }
40
+ }
41
+ return {
42
+ sourceRunId,
43
+ ...result,
44
+ };
45
+ }
46
+ /**
47
+ * Evaluates a run with an optional example and returns the evaluation result.
48
+ * @param run The run to evaluate.
49
+ * @param example The optional example to use for evaluation.
50
+ * @returns A promise that extracts to the evaluation result.
51
+ */
52
+ async evaluateRun(run, example, options) {
53
+ const sourceRunId = (0, uuid_1.v4)();
54
+ const metadata = {
55
+ targetRunId: run.id,
56
+ };
57
+ if ("session_id" in run) {
58
+ metadata["experiment"] = run.session_id;
59
+ }
60
+ const wrappedTraceableFunc = (0, traceable_js_1.wrapFunctionAndEnsureTraceable)(this.func, options || {}, "evaluator");
61
+ // Pass data via `langSmithRunAndExample` key to avoid conflicts with other
62
+ // inputs. This key is extracted in the wrapped function, with `run` and
63
+ // `example` passed to evaluator function as arguments.
64
+ const langSmithRunAndExample = {
65
+ run,
66
+ example,
67
+ };
68
+ const result = (await wrappedTraceableFunc({ langSmithRunAndExample }, {
69
+ metadata,
70
+ }));
71
+ // Check the one required property of EvaluationResult since 'instanceof' is not possible
72
+ if ("key" in result) {
73
+ if (!result.sourceRunId) {
74
+ result.sourceRunId = sourceRunId;
75
+ }
76
+ return result;
77
+ }
78
+ if (typeof result !== "object") {
79
+ throw new Error("Evaluator function must return an object.");
80
+ }
81
+ return this.coerceEvaluationResults(result, sourceRunId);
82
+ }
83
+ }
84
+ exports.DynamicRunEvaluator = DynamicRunEvaluator;
85
+ function runEvaluator(func) {
86
+ return new DynamicRunEvaluator(func);
87
+ }
88
+ exports.runEvaluator = runEvaluator;
@@ -1,4 +1,5 @@
1
- import { Example, Run, ScoreType, ValueType } from "../schemas.js";
1
+ import { Example, FeedbackConfig, Run, ScoreType, ValueType } from "../schemas.js";
2
+ import { RunTreeConfig } from "../run_trees.js";
2
3
  /**
3
4
  * Represents a categorical class.
4
5
  */
@@ -12,31 +13,6 @@ export type Category = {
12
13
  */
13
14
  label: string;
14
15
  };
15
- /**
16
- * Configuration for feedback.
17
- */
18
- export type FeedbackConfig = {
19
- /**
20
- * The type of feedback.
21
- * - "continuous": Feedback with a continuous numeric.
22
- * - "categorical": Feedback with a categorical value (classes)
23
- * - "freeform": Feedback with a freeform text value (notes).
24
- */
25
- type: "continuous" | "categorical" | "freeform";
26
- /**
27
- * The minimum value for continuous feedback.
28
- */
29
- min?: number;
30
- /**
31
- * The maximum value for continuous feedback.
32
- */
33
- max?: number;
34
- /**
35
- * The categories for categorical feedback.
36
- * Each category can be a string or an object with additional properties.
37
- */
38
- categories?: (Category | Record<string, unknown>)[];
39
- };
40
16
  /**
41
17
  * Represents the result of an evaluation.
42
18
  */
@@ -83,6 +59,34 @@ export type EvaluationResult = {
83
59
  */
84
60
  feedbackConfig?: FeedbackConfig;
85
61
  };
62
+ /**
63
+ * Batch evaluation results, if your evaluator wishes
64
+ * to return multiple scores.
65
+ */
66
+ export type EvaluationResults = {
67
+ /**
68
+ * The evaluation results.
69
+ */
70
+ results: Array<EvaluationResult>;
71
+ };
86
72
  export interface RunEvaluator {
87
- evaluateRun(run: Run, example?: Example): Promise<EvaluationResult>;
73
+ evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult>;
74
+ }
75
+ export type RunEvaluatorLike = ((run: Run, example?: Example) => Promise<EvaluationResult | EvaluationResults>) | ((run: Run, example?: Example) => EvaluationResult | EvaluationResults);
76
+ /**
77
+ * Wraps an evaluator function + implements the RunEvaluator interface.
78
+ */
79
+ export declare class DynamicRunEvaluator<Func extends (...args: any[]) => any> implements RunEvaluator {
80
+ func: Func;
81
+ constructor(evaluator: Func);
82
+ private coerceEvaluationResults;
83
+ private coerceEvaluationResult;
84
+ /**
85
+ * Evaluates a run with an optional example and returns the evaluation result.
86
+ * @param run The run to evaluate.
87
+ * @param example The optional example to use for evaluation.
88
+ * @returns A promise that extracts to the evaluation result.
89
+ */
90
+ evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult>;
88
91
  }
92
+ export declare function runEvaluator(func: RunEvaluatorLike): RunEvaluator;
@@ -1 +1,83 @@
1
- export {};
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { wrapFunctionAndEnsureTraceable } from "../traceable.js";
3
+ /**
4
+ * Wraps an evaluator function + implements the RunEvaluator interface.
5
+ */
6
+ export class DynamicRunEvaluator {
7
+ constructor(evaluator) {
8
+ Object.defineProperty(this, "func", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: void 0
13
+ });
14
+ const wrappedFunc = (input) => {
15
+ const runAndExample = input.langSmithRunAndExample;
16
+ return evaluator(...Object.values(runAndExample));
17
+ };
18
+ this.func = wrappedFunc;
19
+ }
20
+ coerceEvaluationResults(results, sourceRunId) {
21
+ if ("results" in results) {
22
+ throw new Error("EvaluationResults not supported yet.");
23
+ }
24
+ return this.coerceEvaluationResult(results, sourceRunId, true);
25
+ }
26
+ coerceEvaluationResult(result, sourceRunId, allowNoKey = false) {
27
+ if ("key" in result) {
28
+ if (!result.sourceRunId) {
29
+ result.sourceRunId = sourceRunId;
30
+ }
31
+ return result;
32
+ }
33
+ if (!("key" in result)) {
34
+ if (allowNoKey) {
35
+ result["key"] = this.func.name;
36
+ }
37
+ }
38
+ return {
39
+ sourceRunId,
40
+ ...result,
41
+ };
42
+ }
43
+ /**
44
+ * Evaluates a run with an optional example and returns the evaluation result.
45
+ * @param run The run to evaluate.
46
+ * @param example The optional example to use for evaluation.
47
+ * @returns A promise that extracts to the evaluation result.
48
+ */
49
+ async evaluateRun(run, example, options) {
50
+ const sourceRunId = uuidv4();
51
+ const metadata = {
52
+ targetRunId: run.id,
53
+ };
54
+ if ("session_id" in run) {
55
+ metadata["experiment"] = run.session_id;
56
+ }
57
+ const wrappedTraceableFunc = wrapFunctionAndEnsureTraceable(this.func, options || {}, "evaluator");
58
+ // Pass data via `langSmithRunAndExample` key to avoid conflicts with other
59
+ // inputs. This key is extracted in the wrapped function, with `run` and
60
+ // `example` passed to evaluator function as arguments.
61
+ const langSmithRunAndExample = {
62
+ run,
63
+ example,
64
+ };
65
+ const result = (await wrappedTraceableFunc({ langSmithRunAndExample }, {
66
+ metadata,
67
+ }));
68
+ // Check the one required property of EvaluationResult since 'instanceof' is not possible
69
+ if ("key" in result) {
70
+ if (!result.sourceRunId) {
71
+ result.sourceRunId = sourceRunId;
72
+ }
73
+ return result;
74
+ }
75
+ if (typeof result !== "object") {
76
+ throw new Error("Evaluator function must return an object.");
77
+ }
78
+ return this.coerceEvaluationResults(result, sourceRunId);
79
+ }
80
+ }
81
+ export function runEvaluator(func) {
82
+ return new DynamicRunEvaluator(func);
83
+ }
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StringEvaluator = void 0;
3
+ exports.evaluate = exports.StringEvaluator = void 0;
4
4
  var string_evaluator_js_1 = require("./string_evaluator.cjs");
5
5
  Object.defineProperty(exports, "StringEvaluator", { enumerable: true, get: function () { return string_evaluator_js_1.StringEvaluator; } });
6
+ var _runner_js_1 = require("./_runner.cjs");
7
+ Object.defineProperty(exports, "evaluate", { enumerable: true, get: function () { return _runner_js_1.evaluate; } });
@@ -1,2 +1,3 @@
1
1
  export { RunEvaluator, EvaluationResult } from "./evaluator.js";
2
2
  export { StringEvaluator, GradingFunctionParams, GradingFunctionResult, } from "./string_evaluator.js";
3
+ export { evaluate, type EvaluateOptions } from "./_runner.js";
@@ -1 +1,2 @@
1
1
  export { StringEvaluator, } from "./string_evaluator.js";
2
+ export { evaluate } from "./_runner.js";
package/dist/index.cjs CHANGED
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "Client", { enumerable: true, get: function () {
6
6
  var run_trees_js_1 = require("./run_trees.cjs");
7
7
  Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () { return run_trees_js_1.RunTree; } });
8
8
  // Update using yarn bump-version
9
- exports.__version__ = "0.1.21";
9
+ exports.__version__ = "0.1.22";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export type { Dataset, Example, TracerSession, Run, Feedback, } from "./schemas.js";
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
- export declare const __version__ = "0.1.21";
4
+ export declare const __version__ = "0.1.22";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export { RunTree } from "./run_trees.js";
3
3
  // Update using yarn bump-version
4
- export const __version__ = "0.1.21";
4
+ export const __version__ = "0.1.22";
@@ -158,6 +158,12 @@ class RunTree {
158
158
  writable: true,
159
159
  value: void 0
160
160
  });
161
+ Object.defineProperty(this, "tracingEnabled", {
162
+ enumerable: true,
163
+ configurable: true,
164
+ writable: true,
165
+ value: void 0
166
+ });
161
167
  const defaultConfig = RunTree.getDefaultConfig();
162
168
  const { metadata, ...config } = originalConfig;
163
169
  const client = config.client ?? new client_js_1.Client();
@@ -238,6 +244,7 @@ class RunTree {
238
244
  parent_run: this,
239
245
  project_name: this.project_name,
240
246
  client: this.client,
247
+ tracingEnabled: this.tracingEnabled,
241
248
  });
242
249
  this.child_runs.push(child);
243
250
  return child;
@@ -20,6 +20,8 @@ export interface RunTreeConfig {
20
20
  outputs?: KVMap;
21
21
  reference_example_id?: string;
22
22
  client?: Client;
23
+ tracingEnabled?: boolean;
24
+ on_end?: (runTree: RunTree) => void;
23
25
  }
24
26
  export interface RunnableConfigLike {
25
27
  /**
@@ -58,6 +60,7 @@ export declare class RunTree implements BaseRun {
58
60
  events?: KVMap[] | undefined;
59
61
  trace_id: string;
60
62
  dotted_order: string;
63
+ tracingEnabled?: boolean;
61
64
  constructor(originalConfig: RunTreeConfig);
62
65
  static fromRunnableConfig(config: RunnableConfigLike, props: {
63
66
  name: string;
package/dist/run_trees.js CHANGED
@@ -131,6 +131,12 @@ export class RunTree {
131
131
  writable: true,
132
132
  value: void 0
133
133
  });
134
+ Object.defineProperty(this, "tracingEnabled", {
135
+ enumerable: true,
136
+ configurable: true,
137
+ writable: true,
138
+ value: void 0
139
+ });
134
140
  const defaultConfig = RunTree.getDefaultConfig();
135
141
  const { metadata, ...config } = originalConfig;
136
142
  const client = config.client ?? new Client();
@@ -211,6 +217,7 @@ export class RunTree {
211
217
  parent_run: this,
212
218
  project_name: this.project_name,
213
219
  client: this.client,
220
+ tracingEnabled: this.tracingEnabled,
214
221
  });
215
222
  this.child_runs.push(child);
216
223
  return child;
package/dist/schemas.d.ts CHANGED
@@ -5,6 +5,9 @@ export interface TracerSession {
5
5
  end_time?: number;
6
6
  description?: string;
7
7
  name?: string;
8
+ /** Extra metadata for the project. */
9
+ extra?: KVMap;
10
+ reference_dataset_id?: string;
8
11
  }
9
12
  export interface TracerSessionResult extends TracerSession {
10
13
  run_count?: number;
@@ -15,7 +18,6 @@ export interface TracerSessionResult extends TracerSession {
15
18
  completion_tokens?: number;
16
19
  last_run_start_time?: number;
17
20
  feedback_stats?: Record<string, unknown>;
18
- reference_dataset_id?: string;
19
21
  run_facets?: KVMap[];
20
22
  }
21
23
  export type KVMap = Record<string, any>;
@@ -78,6 +80,14 @@ export interface BaseRun {
78
80
  */
79
81
  dotted_order?: string;
80
82
  }
83
+ type S3URL = {
84
+ ROOT: {
85
+ /** A pre-signed URL */
86
+ presigned_url: string;
87
+ /** The S3 path to the object in storage */
88
+ s3_url: string;
89
+ };
90
+ };
81
91
  /**
82
92
  * Describes properties of a run when loaded from the database.
83
93
  * Extends the BaseRun interface.
@@ -111,6 +121,10 @@ export interface Run extends BaseRun {
111
121
  parent_run_ids?: string[];
112
122
  /** Whether the run is included in a dataset. */
113
123
  in_dataset?: boolean;
124
+ /** The output S3 URLs */
125
+ outputs_s3_urls?: S3URL;
126
+ /** The input S3 URLs */
127
+ inputs_s3_urls?: S3URL;
114
128
  }
115
129
  export interface RunCreate extends BaseRun {
116
130
  revision_id?: string;
@@ -235,6 +249,9 @@ export interface FeedbackCategory {
235
249
  export interface FeedbackConfig {
236
250
  /**
237
251
  * The type of feedback.
252
+ * - "continuous": Feedback with a continuous numeric.
253
+ * - "categorical": Feedback with a categorical value (classes)
254
+ * - "freeform": Feedback with a freeform text value (notes).
238
255
  */
239
256
  type: "continuous" | "categorical" | "freeform";
240
257
  /**
@@ -246,6 +263,9 @@ export interface FeedbackConfig {
246
263
  */
247
264
  max?: number | null;
248
265
  /**
266
+ * The categories for categorical feedback.
267
+ * Each category can be a string or an object with additional properties.
268
+ *
249
269
  * If feedback is categorical, this defines the valid categories the server will accept.
250
270
  * Not applicable to continuous or freeform feedback types.
251
271
  */
@@ -256,3 +276,4 @@ export interface DatasetDiffInfo {
256
276
  examples_added: string[];
257
277
  examples_removed: string[];
258
278
  }
279
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTraceableFunction = exports.getCurrentRunTree = exports.traceable = void 0;
3
+ exports.wrapFunctionAndEnsureTraceable = exports.isTraceableFunction = exports.getCurrentRunTree = exports.traceable = exports.ROOT = void 0;
4
4
  const async_hooks_1 = require("async_hooks");
5
5
  const run_trees_js_1 = require("./run_trees.cjs");
6
6
  const env_js_1 = require("./utils/env.cjs");
@@ -11,16 +11,48 @@ function isPromiseMethod(x) {
11
11
  return false;
12
12
  }
13
13
  const asyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
14
+ exports.ROOT = Symbol("langsmith:traceable:root");
14
15
  const isAsyncIterable = (x) => x != null &&
15
16
  typeof x === "object" &&
16
17
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
18
  typeof x[Symbol.asyncIterator] === "function";
18
- const getTracingRunTree = (runTree) => {
19
- const tracingEnabled = (0, env_js_1.getEnvironmentVariable)("LANGSMITH_TRACING_V2") === "true" ||
20
- (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_TRACING_V2") === "true";
21
- if (!tracingEnabled) {
19
+ const tracingIsEnabled = (tracingEnabled) => {
20
+ if (tracingEnabled !== undefined) {
21
+ return tracingEnabled;
22
+ }
23
+ const envVars = [
24
+ "LANGSMITH_TRACING_V2",
25
+ "LANGCHAIN_TRACING_V2",
26
+ "LANGSMITH_TRACING",
27
+ "LANGCHAIN_TRACING",
28
+ ];
29
+ return Boolean(envVars.find((envVar) => (0, env_js_1.getEnvironmentVariable)(envVar) === "true"));
30
+ };
31
+ const handleRunInputs = (rawInputs) => {
32
+ const firstInput = rawInputs[0];
33
+ if (firstInput == null) {
34
+ return {};
35
+ }
36
+ if (rawInputs.length > 1) {
37
+ return { args: rawInputs };
38
+ }
39
+ if (isKVMap(firstInput)) {
40
+ return firstInput;
41
+ }
42
+ return { input: firstInput };
43
+ };
44
+ const handleRunOutputs = (rawOutputs) => {
45
+ if (isKVMap(rawOutputs)) {
46
+ return rawOutputs;
47
+ }
48
+ return { outputs: rawOutputs };
49
+ };
50
+ const getTracingRunTree = (runTree, inputs) => {
51
+ const tracingEnabled_ = tracingIsEnabled(runTree.tracingEnabled);
52
+ if (!tracingEnabled_) {
22
53
  return undefined;
23
54
  }
55
+ runTree.inputs = handleRunInputs(inputs);
24
56
  return runTree;
25
57
  };
26
58
  /**
@@ -41,8 +73,6 @@ const getTracingRunTree = (runTree) => {
41
73
  function traceable(wrappedFunc, config) {
42
74
  const { aggregator, argsConfigPath, ...runTreeConfig } = config ?? {};
43
75
  const traceableFunc = (...args) => {
44
- let currentRunTree;
45
- let rawInputs;
46
76
  let ensuredConfig;
47
77
  try {
48
78
  let runtimeConfig;
@@ -88,41 +118,42 @@ function traceable(wrappedFunc, config) {
88
118
  ...runTreeConfig,
89
119
  };
90
120
  }
91
- const previousRunTree = asyncLocalStorage.getStore();
92
- if ((0, run_trees_js_1.isRunTree)(args[0])) {
93
- currentRunTree = args[0];
94
- rawInputs = args.slice(1);
95
- }
96
- else if ((0, run_trees_js_1.isRunnableConfigLike)(args[0])) {
97
- currentRunTree = run_trees_js_1.RunTree.fromRunnableConfig(args[0], ensuredConfig);
98
- rawInputs = args.slice(1);
99
- }
100
- else if (previousRunTree !== undefined) {
101
- currentRunTree = previousRunTree.createChild(ensuredConfig);
102
- rawInputs = args;
103
- }
104
- else {
105
- currentRunTree = new run_trees_js_1.RunTree(ensuredConfig);
106
- rawInputs = args;
107
- }
108
- currentRunTree = getTracingRunTree(currentRunTree);
109
- let inputs;
110
- const firstInput = rawInputs[0];
111
- if (firstInput == null) {
112
- inputs = {};
113
- }
114
- else if (rawInputs.length > 1) {
115
- inputs = { args: rawInputs };
116
- }
117
- else if (isKVMap(firstInput)) {
118
- inputs = firstInput;
119
- }
120
- else {
121
- inputs = { input: firstInput };
122
- }
123
- if (currentRunTree) {
124
- currentRunTree.inputs = inputs;
125
- }
121
+ const [currentRunTree, rawInputs] = (() => {
122
+ const [firstArg, ...restArgs] = args;
123
+ // used for handoff between LangChain.JS and traceable functions
124
+ if ((0, run_trees_js_1.isRunnableConfigLike)(firstArg)) {
125
+ return [
126
+ getTracingRunTree(run_trees_js_1.RunTree.fromRunnableConfig(firstArg, ensuredConfig), restArgs),
127
+ restArgs,
128
+ ];
129
+ }
130
+ // legacy CallbackManagerRunTree used in runOnDataset
131
+ // override ALS and do not pass-through the run tree
132
+ if ((0, run_trees_js_1.isRunTree)(firstArg) &&
133
+ "callbackManager" in firstArg &&
134
+ firstArg.callbackManager != null) {
135
+ return [firstArg, restArgs];
136
+ }
137
+ // when ALS is unreliable, users can manually
138
+ // pass in the run tree
139
+ if (firstArg === exports.ROOT || (0, run_trees_js_1.isRunTree)(firstArg)) {
140
+ const currentRunTree = getTracingRunTree(firstArg === exports.ROOT
141
+ ? new run_trees_js_1.RunTree(ensuredConfig)
142
+ : firstArg.createChild(ensuredConfig), restArgs);
143
+ return [currentRunTree, [currentRunTree, ...restArgs]];
144
+ }
145
+ // Node.JS uses AsyncLocalStorage (ALS) and AsyncResource
146
+ // to allow storing context
147
+ const prevRunFromStore = asyncLocalStorage.getStore();
148
+ if (prevRunFromStore) {
149
+ return [
150
+ getTracingRunTree(prevRunFromStore.createChild(ensuredConfig), args),
151
+ args,
152
+ ];
153
+ }
154
+ const currentRunTree = getTracingRunTree(new run_trees_js_1.RunTree(ensuredConfig), args);
155
+ return [currentRunTree, args];
156
+ })();
126
157
  return asyncLocalStorage.run(currentRunTree, () => {
127
158
  const postRunPromise = currentRunTree?.postRun();
128
159
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -173,6 +204,15 @@ function traceable(wrappedFunc, config) {
173
204
  else {
174
205
  await currentRunTree?.end({ outputs: finalOutputs });
175
206
  }
207
+ const onEnd = config?.on_end;
208
+ if (onEnd) {
209
+ if (!currentRunTree) {
210
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
211
+ }
212
+ else {
213
+ onEnd(currentRunTree);
214
+ }
215
+ }
176
216
  await postRunPromise;
177
217
  await currentRunTree?.patchRun();
178
218
  }
@@ -225,6 +265,15 @@ function traceable(wrappedFunc, config) {
225
265
  else {
226
266
  await currentRunTree?.end({ outputs: finalOutputs });
227
267
  }
268
+ const onEnd = config?.on_end;
269
+ if (onEnd) {
270
+ if (!currentRunTree) {
271
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
272
+ }
273
+ else {
274
+ onEnd(currentRunTree);
275
+ }
276
+ }
228
277
  await postRunPromise;
229
278
  await currentRunTree?.patchRun();
230
279
  }
@@ -233,7 +282,16 @@ function traceable(wrappedFunc, config) {
233
282
  }
234
283
  else {
235
284
  try {
236
- await currentRunTree?.end(isKVMap(rawOutput) ? rawOutput : { outputs: rawOutput });
285
+ await currentRunTree?.end(handleRunOutputs(rawOutput));
286
+ const onEnd = config?.on_end;
287
+ if (onEnd) {
288
+ if (!currentRunTree) {
289
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
290
+ }
291
+ else {
292
+ onEnd(currentRunTree);
293
+ }
294
+ }
237
295
  await postRunPromise;
238
296
  await currentRunTree?.patchRun();
239
297
  }
@@ -246,6 +304,15 @@ function traceable(wrappedFunc, config) {
246
304
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
305
  async (error) => {
248
306
  await currentRunTree?.end(undefined, String(error));
307
+ const onEnd = config?.on_end;
308
+ if (onEnd) {
309
+ if (!currentRunTree) {
310
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
311
+ }
312
+ else {
313
+ onEnd(currentRunTree);
314
+ }
315
+ }
249
316
  await postRunPromise;
250
317
  await currentRunTree?.patchRun();
251
318
  throw error;
@@ -302,3 +369,13 @@ function isKVMap(x) {
302
369
  // eslint-disable-next-line no-instanceof/no-instanceof
303
370
  !(x instanceof Date));
304
371
  }
372
+ function wrapFunctionAndEnsureTraceable(target, options, name = "target") {
373
+ if (typeof target === "function") {
374
+ return traceable(target, {
375
+ ...options,
376
+ name,
377
+ });
378
+ }
379
+ throw new Error("Target must be runnable function");
380
+ }
381
+ exports.wrapFunctionAndEnsureTraceable = wrapFunctionAndEnsureTraceable;
@@ -1,13 +1,17 @@
1
1
  import { RunTree, RunTreeConfig, RunnableConfigLike } from "./run_trees.js";
2
+ export declare const ROOT: unique symbol;
2
3
  export type RunTreeLike = RunTree;
3
4
  type SmartPromise<T> = T extends AsyncGenerator ? T : T extends Promise<unknown> ? T : Promise<T>;
4
5
  type WrapArgReturnPair<Pair> = Pair extends [
5
6
  infer Args extends any[],
6
7
  infer Return
7
- ] ? {
8
+ ] ? Args extends [RunTreeLike, ...infer RestArgs] ? {
9
+ (runTree: RunTreeLike | typeof ROOT, ...args: RestArgs): SmartPromise<Return>;
10
+ (config: RunnableConfigLike, ...args: RestArgs): SmartPromise<Return>;
11
+ } : {
8
12
  (...args: Args): SmartPromise<Return>;
9
- (...args: [runTree: RunTreeLike, ...rest: Args]): SmartPromise<Return>;
10
- (...args: [config: RunnableConfigLike, ...rest: Args]): SmartPromise<Return>;
13
+ (runTree: RunTreeLike, ...rest: Args): SmartPromise<Return>;
14
+ (config: RunnableConfigLike, ...args: Args): SmartPromise<Return>;
11
15
  } : never;
12
16
  type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
13
17
  export type TraceableFunction<Func extends (...args: any[]) => any> = Func extends {
@@ -57,4 +61,5 @@ export declare function traceable<Func extends (...args: any[]) => any>(wrappedF
57
61
  */
58
62
  export declare function getCurrentRunTree(): RunTree;
59
63
  export declare function isTraceableFunction(x: unknown): x is TraceableFunction<any>;
64
+ export declare function wrapFunctionAndEnsureTraceable<Func extends (...args: any[]) => any>(target: Func, options: Partial<RunTreeConfig>, name?: string): TraceableFunction<Func>;
60
65
  export {};