langsmith 0.3.29 → 0.3.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -1083,7 +1083,7 @@ class Client {
1083
1083
  async readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
1084
1084
  (0, _uuid_js_1.assertUuid)(runId);
1085
1085
  let run = await this._get(`/runs/${runId}`);
1086
- if (loadChildRuns && run.child_run_ids) {
1086
+ if (loadChildRuns) {
1087
1087
  run = await this._loadChildRuns(run);
1088
1088
  }
1089
1089
  return run;
@@ -1122,7 +1122,11 @@ class Client {
1122
1122
  }
1123
1123
  }
1124
1124
  async _loadChildRuns(run) {
1125
- const childRuns = await toArray(this.listRuns({ id: run.child_run_ids }));
1125
+ const childRuns = await toArray(this.listRuns({
1126
+ isRoot: false,
1127
+ projectId: run.session_id,
1128
+ traceId: run.trace_id,
1129
+ }));
1126
1130
  const treemap = {};
1127
1131
  const runs = {};
1128
1132
  // TODO: make dotted order required when the migration finishes
@@ -1132,11 +1136,14 @@ class Client {
1132
1136
  childRun.parent_run_id === undefined) {
1133
1137
  throw new Error(`Child run ${childRun.id} has no parent`);
1134
1138
  }
1135
- if (!(childRun.parent_run_id in treemap)) {
1136
- treemap[childRun.parent_run_id] = [];
1139
+ if (childRun.dotted_order?.startsWith(run.dotted_order ?? "") &&
1140
+ childRun.id !== run.id) {
1141
+ if (!(childRun.parent_run_id in treemap)) {
1142
+ treemap[childRun.parent_run_id] = [];
1143
+ }
1144
+ treemap[childRun.parent_run_id].push(childRun);
1145
+ runs[childRun.id] = childRun;
1137
1146
  }
1138
- treemap[childRun.parent_run_id].push(childRun);
1139
- runs[childRun.id] = childRun;
1140
1147
  }
1141
1148
  run.child_runs = treemap[run.id] || [];
1142
1149
  for (const runId in treemap) {
@@ -1243,7 +1250,6 @@ class Client {
1243
1250
  }
1244
1251
  const default_select = [
1245
1252
  "app_path",
1246
- "child_run_ids",
1247
1253
  "completion_cost",
1248
1254
  "completion_tokens",
1249
1255
  "dotted_order",
package/dist/client.js CHANGED
@@ -1045,7 +1045,7 @@ export class Client {
1045
1045
  async readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
1046
1046
  assertUuid(runId);
1047
1047
  let run = await this._get(`/runs/${runId}`);
1048
- if (loadChildRuns && run.child_run_ids) {
1048
+ if (loadChildRuns) {
1049
1049
  run = await this._loadChildRuns(run);
1050
1050
  }
1051
1051
  return run;
@@ -1084,7 +1084,11 @@ export class Client {
1084
1084
  }
1085
1085
  }
1086
1086
  async _loadChildRuns(run) {
1087
- const childRuns = await toArray(this.listRuns({ id: run.child_run_ids }));
1087
+ const childRuns = await toArray(this.listRuns({
1088
+ isRoot: false,
1089
+ projectId: run.session_id,
1090
+ traceId: run.trace_id,
1091
+ }));
1088
1092
  const treemap = {};
1089
1093
  const runs = {};
1090
1094
  // TODO: make dotted order required when the migration finishes
@@ -1094,11 +1098,14 @@ export class Client {
1094
1098
  childRun.parent_run_id === undefined) {
1095
1099
  throw new Error(`Child run ${childRun.id} has no parent`);
1096
1100
  }
1097
- if (!(childRun.parent_run_id in treemap)) {
1098
- treemap[childRun.parent_run_id] = [];
1101
+ if (childRun.dotted_order?.startsWith(run.dotted_order ?? "") &&
1102
+ childRun.id !== run.id) {
1103
+ if (!(childRun.parent_run_id in treemap)) {
1104
+ treemap[childRun.parent_run_id] = [];
1105
+ }
1106
+ treemap[childRun.parent_run_id].push(childRun);
1107
+ runs[childRun.id] = childRun;
1099
1108
  }
1100
- treemap[childRun.parent_run_id].push(childRun);
1101
- runs[childRun.id] = childRun;
1102
1109
  }
1103
1110
  run.child_runs = treemap[run.id] || [];
1104
1111
  for (const runId in treemap) {
@@ -1205,7 +1212,6 @@ export class Client {
1205
1212
  }
1206
1213
  const default_select = [
1207
1214
  "app_path",
1208
- "child_run_ids",
1209
1215
  "completion_cost",
1210
1216
  "completion_tokens",
1211
1217
  "dotted_order",
package/dist/index.cjs CHANGED
@@ -8,4 +8,4 @@ Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () {
8
8
  var fetch_js_1 = require("./singletons/fetch.cjs");
9
9
  Object.defineProperty(exports, "overrideFetchImplementation", { enumerable: true, get: function () { return fetch_js_1.overrideFetchImplementation; } });
10
10
  // Update using yarn bump-version
11
- exports.__version__ = "0.3.29";
11
+ exports.__version__ = "0.3.30";
package/dist/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export { Client, type ClientConfig, type LangSmithTracingClientInterface, } from
2
2
  export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, } from "./schemas.js";
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
4
  export { overrideFetchImplementation } from "./singletons/fetch.js";
5
- export declare const __version__ = "0.3.29";
5
+ export declare const __version__ = "0.3.30";
package/dist/index.js CHANGED
@@ -2,4 +2,4 @@ export { Client, } from "./client.js";
2
2
  export { RunTree } from "./run_trees.js";
3
3
  export { overrideFetchImplementation } from "./singletons/fetch.js";
4
4
  // Update using yarn bump-version
5
- export const __version__ = "0.3.29";
5
+ export const __version__ = "0.3.30";
@@ -292,6 +292,18 @@ class RunTree {
292
292
  }
293
293
  }
294
294
  }
295
+ set metadata(metadata) {
296
+ this.extra = {
297
+ ...this.extra,
298
+ metadata: {
299
+ ...this.extra?.metadata,
300
+ ...metadata,
301
+ },
302
+ };
303
+ }
304
+ get metadata() {
305
+ return this.extra?.metadata;
306
+ }
295
307
  static getDefaultConfig() {
296
308
  return {
297
309
  id: uuid.v4(),
@@ -79,6 +79,8 @@ export declare class RunTree implements BaseRun {
79
79
  */
80
80
  attachments?: Attachments;
81
81
  constructor(originalConfig: RunTreeConfig | RunTree);
82
+ set metadata(metadata: KVMap);
83
+ get metadata(): KVMap;
82
84
  private static getDefaultConfig;
83
85
  private static getSharedClient;
84
86
  createChild(config: RunTreeConfig): RunTree;
package/dist/run_trees.js CHANGED
@@ -253,6 +253,18 @@ export class RunTree {
253
253
  }
254
254
  }
255
255
  }
256
+ set metadata(metadata) {
257
+ this.extra = {
258
+ ...this.extra,
259
+ metadata: {
260
+ ...this.extra?.metadata,
261
+ ...metadata,
262
+ },
263
+ };
264
+ }
265
+ get metadata() {
266
+ return this.extra?.metadata;
267
+ }
256
268
  static getDefaultConfig() {
257
269
  return {
258
270
  id: uuid.v4(),
package/dist/schemas.d.ts CHANGED
@@ -531,5 +531,26 @@ export type UsageMetadata = {
531
531
  * Does *not* need to sum to full output token count. Does *not* need to have all keys.
532
532
  */
533
533
  output_token_details?: OutputTokenDetails;
534
+ /**
535
+ * The cost of the input tokens.
536
+ */
537
+ input_cost?: number;
538
+ /**
539
+ * The cost of the output tokens.
540
+ */
541
+ output_cost?: number;
542
+ /**
543
+ * The total cost of the tokens.
544
+ */
545
+ total_cost?: number;
546
+ /**
547
+ * The cost details of the input tokens.
548
+ */
549
+ input_cost_details?: Record<string, unknown>;
550
+ /**
551
+ * The cost details of the output tokens.
552
+ */
553
+ output_cost_details?: Record<string, unknown>;
534
554
  };
555
+ export type ExtractedUsageMetadata = Partial<UsageMetadata>;
535
556
  export {};
@@ -35,22 +35,64 @@ const handleRunInputs = (inputs, processInputs) => {
35
35
  return inputs;
36
36
  }
37
37
  };
38
- const handleRunOutputs = (rawOutputs, processOutputs) => {
38
+ const _extractUsage = (runData) => {
39
+ const usageMetadataFromMetadata = (runData.runTree.extra.metadata ?? {})
40
+ .usage_metadata;
41
+ return runData.outputs.usage_metadata ?? usageMetadataFromMetadata;
42
+ };
43
+ function validateExtractedUsageMetadata(data) {
44
+ const allowedKeys = new Set([
45
+ "input_tokens",
46
+ "output_tokens",
47
+ "total_tokens",
48
+ "input_token_details",
49
+ "output_token_details",
50
+ "input_cost",
51
+ "output_cost",
52
+ "total_cost",
53
+ "input_cost_details",
54
+ "output_cost_details",
55
+ ]);
56
+ const extraKeys = Object.keys(data).filter((key) => !allowedKeys.has(key));
57
+ if (extraKeys.length > 0) {
58
+ throw new Error(`Unexpected keys in usage metadata: ${extraKeys.join(", ")}`);
59
+ }
60
+ return data;
61
+ }
62
+ // Note: This mutates the run tree
63
+ function handleRunOutputs(params) {
64
+ const { runTree, rawOutputs, processOutputsFn } = params;
39
65
  let outputs;
40
66
  if ((0, asserts_js_1.isKVMap)(rawOutputs)) {
41
- outputs = rawOutputs;
67
+ outputs = { ...rawOutputs };
42
68
  }
43
69
  else {
44
70
  outputs = { outputs: rawOutputs };
45
71
  }
46
72
  try {
47
- return processOutputs(outputs);
73
+ outputs = processOutputsFn(outputs);
48
74
  }
49
75
  catch (e) {
50
- console.error("Error occurred during processOutputs. Sending raw outputs:", e);
51
- return outputs;
76
+ console.error("Error occurred during processOutputs. Sending unprocessed outputs:", e);
52
77
  }
53
- };
78
+ if (runTree !== undefined) {
79
+ let usageMetadata;
80
+ try {
81
+ usageMetadata = _extractUsage({ runTree, outputs });
82
+ }
83
+ catch (e) {
84
+ console.error("Error occurred while extracting usage metadata:", e);
85
+ }
86
+ if (usageMetadata !== undefined) {
87
+ runTree.extra.metadata = {
88
+ ...runTree.extra.metadata,
89
+ usage_metadata: validateExtractedUsageMetadata(usageMetadata),
90
+ };
91
+ outputs.usage_metadata = usageMetadata;
92
+ }
93
+ }
94
+ return outputs;
95
+ }
54
96
  const handleRunAttachments = (rawInputs, extractAttachments) => {
55
97
  if (!extractAttachments) {
56
98
  return [undefined, rawInputs];
@@ -358,7 +400,12 @@ function traceable(wrappedFunc, config) {
358
400
  : reader.read());
359
401
  if (result.done) {
360
402
  finished = true;
361
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
403
+ const processedOutputs = handleRunOutputs({
404
+ runTree: currentRunTree,
405
+ rawOutputs: await handleChunks(chunks),
406
+ processOutputsFn,
407
+ });
408
+ await currentRunTree?.end(processedOutputs);
362
409
  await handleEnd();
363
410
  controller.close();
364
411
  break;
@@ -377,7 +424,12 @@ function traceable(wrappedFunc, config) {
377
424
  async cancel(reason) {
378
425
  if (!finished)
379
426
  await currentRunTree?.end(undefined, "Cancelled");
380
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
427
+ const processedOutputs = handleRunOutputs({
428
+ runTree: currentRunTree,
429
+ rawOutputs: await handleChunks(chunks),
430
+ processOutputsFn,
431
+ });
432
+ await currentRunTree?.end(processedOutputs);
381
433
  await handleEnd();
382
434
  return reader.cancel(reason);
383
435
  },
@@ -414,7 +466,12 @@ function traceable(wrappedFunc, config) {
414
466
  finally {
415
467
  if (!finished)
416
468
  await currentRunTree?.end(undefined, "Cancelled");
417
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
469
+ const processedOutputs = handleRunOutputs({
470
+ runTree: currentRunTree,
471
+ rawOutputs: await handleChunks(chunks),
472
+ processOutputsFn,
473
+ });
474
+ await currentRunTree?.end(processedOutputs);
418
475
  await handleEnd();
419
476
  }
420
477
  }
@@ -494,12 +551,17 @@ function traceable(wrappedFunc, config) {
494
551
  if ((0, asserts_js_1.isGenerator)(wrappedFunc) && (0, asserts_js_1.isIteratorLike)(rawOutput)) {
495
552
  const chunks = gatherAll(rawOutput);
496
553
  try {
497
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks.reduce((memo, { value, done }) => {
498
- if (!done || typeof value !== "undefined") {
499
- memo.push(value);
500
- }
501
- return memo;
502
- }, [])), processOutputsFn));
554
+ const processedOutputs = handleRunOutputs({
555
+ runTree: currentRunTree,
556
+ rawOutputs: await handleChunks(chunks.reduce((memo, { value, done }) => {
557
+ if (!done || typeof value !== "undefined") {
558
+ memo.push(value);
559
+ }
560
+ return memo;
561
+ }, [])),
562
+ processOutputsFn,
563
+ });
564
+ await currentRunTree?.end(processedOutputs);
503
565
  await handleEnd();
504
566
  }
505
567
  catch (e) {
@@ -514,7 +576,12 @@ function traceable(wrappedFunc, config) {
514
576
  })();
515
577
  }
516
578
  try {
517
- await currentRunTree?.end(handleRunOutputs(rawOutput, processOutputsFn));
579
+ const processedOutputs = handleRunOutputs({
580
+ runTree: currentRunTree,
581
+ rawOutputs: rawOutput,
582
+ processOutputsFn,
583
+ });
584
+ await currentRunTree?.end(processedOutputs);
518
585
  await handleEnd();
519
586
  }
520
587
  finally {
package/dist/traceable.js CHANGED
@@ -31,22 +31,64 @@ const handleRunInputs = (inputs, processInputs) => {
31
31
  return inputs;
32
32
  }
33
33
  };
34
- const handleRunOutputs = (rawOutputs, processOutputs) => {
34
+ const _extractUsage = (runData) => {
35
+ const usageMetadataFromMetadata = (runData.runTree.extra.metadata ?? {})
36
+ .usage_metadata;
37
+ return runData.outputs.usage_metadata ?? usageMetadataFromMetadata;
38
+ };
39
+ function validateExtractedUsageMetadata(data) {
40
+ const allowedKeys = new Set([
41
+ "input_tokens",
42
+ "output_tokens",
43
+ "total_tokens",
44
+ "input_token_details",
45
+ "output_token_details",
46
+ "input_cost",
47
+ "output_cost",
48
+ "total_cost",
49
+ "input_cost_details",
50
+ "output_cost_details",
51
+ ]);
52
+ const extraKeys = Object.keys(data).filter((key) => !allowedKeys.has(key));
53
+ if (extraKeys.length > 0) {
54
+ throw new Error(`Unexpected keys in usage metadata: ${extraKeys.join(", ")}`);
55
+ }
56
+ return data;
57
+ }
58
+ // Note: This mutates the run tree
59
+ function handleRunOutputs(params) {
60
+ const { runTree, rawOutputs, processOutputsFn } = params;
35
61
  let outputs;
36
62
  if (isKVMap(rawOutputs)) {
37
- outputs = rawOutputs;
63
+ outputs = { ...rawOutputs };
38
64
  }
39
65
  else {
40
66
  outputs = { outputs: rawOutputs };
41
67
  }
42
68
  try {
43
- return processOutputs(outputs);
69
+ outputs = processOutputsFn(outputs);
44
70
  }
45
71
  catch (e) {
46
- console.error("Error occurred during processOutputs. Sending raw outputs:", e);
47
- return outputs;
72
+ console.error("Error occurred during processOutputs. Sending unprocessed outputs:", e);
48
73
  }
49
- };
74
+ if (runTree !== undefined) {
75
+ let usageMetadata;
76
+ try {
77
+ usageMetadata = _extractUsage({ runTree, outputs });
78
+ }
79
+ catch (e) {
80
+ console.error("Error occurred while extracting usage metadata:", e);
81
+ }
82
+ if (usageMetadata !== undefined) {
83
+ runTree.extra.metadata = {
84
+ ...runTree.extra.metadata,
85
+ usage_metadata: validateExtractedUsageMetadata(usageMetadata),
86
+ };
87
+ outputs.usage_metadata = usageMetadata;
88
+ }
89
+ }
90
+ return outputs;
91
+ }
50
92
  const handleRunAttachments = (rawInputs, extractAttachments) => {
51
93
  if (!extractAttachments) {
52
94
  return [undefined, rawInputs];
@@ -354,7 +396,12 @@ export function traceable(wrappedFunc, config) {
354
396
  : reader.read());
355
397
  if (result.done) {
356
398
  finished = true;
357
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
399
+ const processedOutputs = handleRunOutputs({
400
+ runTree: currentRunTree,
401
+ rawOutputs: await handleChunks(chunks),
402
+ processOutputsFn,
403
+ });
404
+ await currentRunTree?.end(processedOutputs);
358
405
  await handleEnd();
359
406
  controller.close();
360
407
  break;
@@ -373,7 +420,12 @@ export function traceable(wrappedFunc, config) {
373
420
  async cancel(reason) {
374
421
  if (!finished)
375
422
  await currentRunTree?.end(undefined, "Cancelled");
376
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
423
+ const processedOutputs = handleRunOutputs({
424
+ runTree: currentRunTree,
425
+ rawOutputs: await handleChunks(chunks),
426
+ processOutputsFn,
427
+ });
428
+ await currentRunTree?.end(processedOutputs);
377
429
  await handleEnd();
378
430
  return reader.cancel(reason);
379
431
  },
@@ -410,7 +462,12 @@ export function traceable(wrappedFunc, config) {
410
462
  finally {
411
463
  if (!finished)
412
464
  await currentRunTree?.end(undefined, "Cancelled");
413
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks), processOutputsFn));
465
+ const processedOutputs = handleRunOutputs({
466
+ runTree: currentRunTree,
467
+ rawOutputs: await handleChunks(chunks),
468
+ processOutputsFn,
469
+ });
470
+ await currentRunTree?.end(processedOutputs);
414
471
  await handleEnd();
415
472
  }
416
473
  }
@@ -490,12 +547,17 @@ export function traceable(wrappedFunc, config) {
490
547
  if (isGenerator(wrappedFunc) && isIteratorLike(rawOutput)) {
491
548
  const chunks = gatherAll(rawOutput);
492
549
  try {
493
- await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks.reduce((memo, { value, done }) => {
494
- if (!done || typeof value !== "undefined") {
495
- memo.push(value);
496
- }
497
- return memo;
498
- }, [])), processOutputsFn));
550
+ const processedOutputs = handleRunOutputs({
551
+ runTree: currentRunTree,
552
+ rawOutputs: await handleChunks(chunks.reduce((memo, { value, done }) => {
553
+ if (!done || typeof value !== "undefined") {
554
+ memo.push(value);
555
+ }
556
+ return memo;
557
+ }, [])),
558
+ processOutputsFn,
559
+ });
560
+ await currentRunTree?.end(processedOutputs);
499
561
  await handleEnd();
500
562
  }
501
563
  catch (e) {
@@ -510,7 +572,12 @@ export function traceable(wrappedFunc, config) {
510
572
  })();
511
573
  }
512
574
  try {
513
- await currentRunTree?.end(handleRunOutputs(rawOutput, processOutputsFn));
575
+ const processedOutputs = handleRunOutputs({
576
+ runTree: currentRunTree,
577
+ rawOutputs: rawOutput,
578
+ processOutputsFn,
579
+ });
580
+ await currentRunTree?.end(processedOutputs);
514
581
  await handleEnd();
515
582
  }
516
583
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.3.29",
3
+ "version": "0.3.30",
4
4
  "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
5
5
  "packageManager": "yarn@1.22.19",
6
6
  "files": [