langsmith 0.8.9 → 0.8.10
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 +33 -4
- package/dist/client.d.ts +10 -6
- package/dist/client.js +33 -4
- package/dist/experimental/vercel/_agent_type.cjs +30 -0
- package/dist/experimental/vercel/_agent_type.d.ts +5 -0
- package/dist/experimental/vercel/_agent_type.js +26 -0
- package/dist/experimental/vercel/telemetry.cjs +2 -7
- package/dist/experimental/vercel/telemetry.js +2 -7
- package/dist/experimental/vercel/wrap.cjs +5 -11
- package/dist/experimental/vercel/wrap.js +6 -12
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/_git.cjs +28 -1
- package/dist/utils/_git.js +28 -1
- package/dist/utils/ls_agent_type.cjs +31 -0
- package/dist/utils/ls_agent_type.d.ts +9 -0
- package/dist/utils/ls_agent_type.js +25 -0
- package/dist/utils/profiles.cjs +125 -1
- package/dist/utils/profiles.d.ts +6 -0
- package/dist/utils/profiles.js +124 -1
- package/dist/wrappers/openai.cjs +4 -0
- package/dist/wrappers/openai.js +4 -0
- package/dist/wrappers/openai_agents.cjs +15 -12
- package/dist/wrappers/openai_agents.js +15 -12
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -893,7 +893,8 @@ class Client {
|
|
|
893
893
|
config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
|
|
894
894
|
this.hideOutputs =
|
|
895
895
|
config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
|
|
896
|
-
this.hideMetadata =
|
|
896
|
+
this.hideMetadata =
|
|
897
|
+
config.hideMetadata ?? config.anonymizer ?? defaultConfig.hideMetadata;
|
|
897
898
|
this.anonymizer = config.anonymizer;
|
|
898
899
|
this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false;
|
|
899
900
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
@@ -1555,6 +1556,9 @@ class Client {
|
|
|
1555
1556
|
const batchSizeBytes = batch.reduce((sum, item) => sum + (item.size ?? 0), 0);
|
|
1556
1557
|
try {
|
|
1557
1558
|
if (this.langSmithToOTELTranslator !== undefined) {
|
|
1559
|
+
for (const item of batch) {
|
|
1560
|
+
item.item = await this._maskRunMetadata(item.item);
|
|
1561
|
+
}
|
|
1558
1562
|
this._sendBatchToOTELTranslator(batch);
|
|
1559
1563
|
}
|
|
1560
1564
|
else {
|
|
@@ -1635,6 +1639,25 @@ class Client {
|
|
|
1635
1639
|
this.langSmithToOTELTranslator.exportBatch(operations, otelContextMap);
|
|
1636
1640
|
}
|
|
1637
1641
|
}
|
|
1642
|
+
async _maskRunMetadata(run) {
|
|
1643
|
+
if (run.extra?.metadata == null) {
|
|
1644
|
+
return run;
|
|
1645
|
+
}
|
|
1646
|
+
return {
|
|
1647
|
+
...run,
|
|
1648
|
+
extra: {
|
|
1649
|
+
...run.extra,
|
|
1650
|
+
metadata: await this.processMetadata(run.extra.metadata),
|
|
1651
|
+
},
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
async _mergeRuntimeEnvAndMaskMetadata(run) {
|
|
1655
|
+
const merged = mergeRuntimeEnvIntoRun(run, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo);
|
|
1656
|
+
if (this.omitTracedRuntimeInfo) {
|
|
1657
|
+
return merged;
|
|
1658
|
+
}
|
|
1659
|
+
return this._maskRunMetadata(merged);
|
|
1660
|
+
}
|
|
1638
1661
|
async processRunOperation(item) {
|
|
1639
1662
|
clearTimeout(this.autoBatchTimeout);
|
|
1640
1663
|
this.autoBatchTimeout = undefined;
|
|
@@ -1791,7 +1814,7 @@ class Client {
|
|
|
1791
1814
|
}).catch(console.error);
|
|
1792
1815
|
return;
|
|
1793
1816
|
}
|
|
1794
|
-
const mergedRunCreateParam =
|
|
1817
|
+
const mergedRunCreateParam = await this._mergeRuntimeEnvAndMaskMetadata(runCreate);
|
|
1795
1818
|
if (options?.apiKey !== undefined) {
|
|
1796
1819
|
headers["x-api-key"] = options.apiKey;
|
|
1797
1820
|
}
|
|
@@ -2980,7 +3003,7 @@ class Client {
|
|
|
2980
3003
|
_hostUrl: this.getHostUrl(),
|
|
2981
3004
|
}));
|
|
2982
3005
|
}
|
|
2983
|
-
async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, }) {
|
|
3006
|
+
async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, tagValueIds = null, }) {
|
|
2984
3007
|
const upsert_ = upsert ? `?upsert=true` : "";
|
|
2985
3008
|
const endpoint = `${this.apiUrl}/sessions${upsert_}`;
|
|
2986
3009
|
const extra = projectExtra || {};
|
|
@@ -3004,6 +3027,9 @@ class Client {
|
|
|
3004
3027
|
if (evaluatorKeys != null && evaluatorKeys.length > 0) {
|
|
3005
3028
|
body["evaluator_keys"] = evaluatorKeys;
|
|
3006
3029
|
}
|
|
3030
|
+
if (tagValueIds !== null) {
|
|
3031
|
+
body["tag_value_ids"] = tagValueIds;
|
|
3032
|
+
}
|
|
3007
3033
|
const serializedBody = JSON.stringify(body);
|
|
3008
3034
|
const response = await this.caller.call(async () => {
|
|
3009
3035
|
const res = await this._fetch(endpoint, {
|
|
@@ -3247,7 +3273,7 @@ class Client {
|
|
|
3247
3273
|
const result = await response.json();
|
|
3248
3274
|
return result;
|
|
3249
3275
|
}
|
|
3250
|
-
async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, } = {}) {
|
|
3276
|
+
async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, tagValueIds, } = {}) {
|
|
3251
3277
|
const body = {
|
|
3252
3278
|
name,
|
|
3253
3279
|
description,
|
|
@@ -3262,6 +3288,9 @@ class Client {
|
|
|
3262
3288
|
if (outputsSchema) {
|
|
3263
3289
|
body.outputs_schema_definition = outputsSchema;
|
|
3264
3290
|
}
|
|
3291
|
+
if (tagValueIds !== undefined) {
|
|
3292
|
+
body.tag_value_ids = tagValueIds;
|
|
3293
|
+
}
|
|
3265
3294
|
const serializedBody = JSON.stringify(body);
|
|
3266
3295
|
const response = await this.caller.call(async () => {
|
|
3267
3296
|
const res = await this._fetch(`${this.apiUrl}/datasets`, {
|
package/dist/client.d.ts
CHANGED
|
@@ -20,11 +20,11 @@ export interface ClientConfig {
|
|
|
20
20
|
timeout_ms?: number;
|
|
21
21
|
webUrl?: string;
|
|
22
22
|
/**
|
|
23
|
-
* A function applied for masking serialized run inputs and
|
|
24
|
-
* before sending to the API. Can be called with raw inputs, raw
|
|
25
|
-
* outputs, or a nested `{ error: string }` object for errors.
|
|
23
|
+
* A function applied for masking serialized run inputs, outputs and
|
|
24
|
+
* metadata, before sending to the API. Can be called with raw inputs, raw
|
|
25
|
+
* outputs, raw metadata, or a nested `{ error: string }` object for errors.
|
|
26
26
|
*
|
|
27
|
-
* If a `hideInputs` or `
|
|
27
|
+
* If a `hideInputs`, `hideOutputs` or `hideMetadata` function is present,
|
|
28
28
|
* the client will call it instead of the anonymizer as appropriate.
|
|
29
29
|
*/
|
|
30
30
|
anonymizer?: (values: KVMap) => KVMap | Promise<KVMap>;
|
|
@@ -413,6 +413,7 @@ export type CreateProjectParams = {
|
|
|
413
413
|
numExamples?: number | null;
|
|
414
414
|
numRepetitions?: number | null;
|
|
415
415
|
evaluatorKeys?: string[] | null;
|
|
416
|
+
tagValueIds?: string[] | null;
|
|
416
417
|
};
|
|
417
418
|
type AutoBatchQueueItem = {
|
|
418
419
|
action: "create" | "update";
|
|
@@ -670,6 +671,8 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
670
671
|
private static _writeTraceToFallbackDir;
|
|
671
672
|
private _processBatch;
|
|
672
673
|
private _sendBatchToOTELTranslator;
|
|
674
|
+
private _maskRunMetadata;
|
|
675
|
+
private _mergeRuntimeEnvAndMaskMetadata;
|
|
673
676
|
private processRunOperation;
|
|
674
677
|
protected _getServerInfo(): Promise<any>;
|
|
675
678
|
private _checkStainlessVersion;
|
|
@@ -872,7 +875,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
872
875
|
listSharedExamples(shareToken: string, options?: {
|
|
873
876
|
exampleIds?: string[];
|
|
874
877
|
}): Promise<Example[]>;
|
|
875
|
-
createProject({ projectName, description, metadata, upsert, projectExtra, referenceDatasetId, numExamples, numRepetitions, evaluatorKeys, }: CreateProjectParams): Promise<TracerSession>;
|
|
878
|
+
createProject({ projectName, description, metadata, upsert, projectExtra, referenceDatasetId, numExamples, numRepetitions, evaluatorKeys, tagValueIds, }: CreateProjectParams): Promise<TracerSession>;
|
|
876
879
|
updateProject(projectId: string, { name, description, metadata, projectExtra, endTime, }: {
|
|
877
880
|
name?: string | null;
|
|
878
881
|
description?: string | null;
|
|
@@ -914,12 +917,13 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
914
917
|
projectName?: string;
|
|
915
918
|
}): Promise<void>;
|
|
916
919
|
uploadCsv({ csvFile, fileName, inputKeys, outputKeys, description, dataType, name, }: UploadCSVParams): Promise<Dataset>;
|
|
917
|
-
createDataset(name: string, { description, dataType, inputsSchema, outputsSchema, metadata, }?: {
|
|
920
|
+
createDataset(name: string, { description, dataType, inputsSchema, outputsSchema, metadata, tagValueIds, }?: {
|
|
918
921
|
description?: string;
|
|
919
922
|
dataType?: DataType;
|
|
920
923
|
inputsSchema?: KVMap;
|
|
921
924
|
outputsSchema?: KVMap;
|
|
922
925
|
metadata?: RecordStringAny;
|
|
926
|
+
tagValueIds?: string[];
|
|
923
927
|
}): Promise<Dataset>;
|
|
924
928
|
readDataset({ datasetId, datasetName, }: {
|
|
925
929
|
datasetId?: string;
|
package/dist/client.js
CHANGED
|
@@ -854,7 +854,8 @@ export class Client {
|
|
|
854
854
|
config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
|
|
855
855
|
this.hideOutputs =
|
|
856
856
|
config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
|
|
857
|
-
this.hideMetadata =
|
|
857
|
+
this.hideMetadata =
|
|
858
|
+
config.hideMetadata ?? config.anonymizer ?? defaultConfig.hideMetadata;
|
|
858
859
|
this.anonymizer = config.anonymizer;
|
|
859
860
|
this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false;
|
|
860
861
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
@@ -1516,6 +1517,9 @@ export class Client {
|
|
|
1516
1517
|
const batchSizeBytes = batch.reduce((sum, item) => sum + (item.size ?? 0), 0);
|
|
1517
1518
|
try {
|
|
1518
1519
|
if (this.langSmithToOTELTranslator !== undefined) {
|
|
1520
|
+
for (const item of batch) {
|
|
1521
|
+
item.item = await this._maskRunMetadata(item.item);
|
|
1522
|
+
}
|
|
1519
1523
|
this._sendBatchToOTELTranslator(batch);
|
|
1520
1524
|
}
|
|
1521
1525
|
else {
|
|
@@ -1596,6 +1600,25 @@ export class Client {
|
|
|
1596
1600
|
this.langSmithToOTELTranslator.exportBatch(operations, otelContextMap);
|
|
1597
1601
|
}
|
|
1598
1602
|
}
|
|
1603
|
+
async _maskRunMetadata(run) {
|
|
1604
|
+
if (run.extra?.metadata == null) {
|
|
1605
|
+
return run;
|
|
1606
|
+
}
|
|
1607
|
+
return {
|
|
1608
|
+
...run,
|
|
1609
|
+
extra: {
|
|
1610
|
+
...run.extra,
|
|
1611
|
+
metadata: await this.processMetadata(run.extra.metadata),
|
|
1612
|
+
},
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
async _mergeRuntimeEnvAndMaskMetadata(run) {
|
|
1616
|
+
const merged = mergeRuntimeEnvIntoRun(run, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo);
|
|
1617
|
+
if (this.omitTracedRuntimeInfo) {
|
|
1618
|
+
return merged;
|
|
1619
|
+
}
|
|
1620
|
+
return this._maskRunMetadata(merged);
|
|
1621
|
+
}
|
|
1599
1622
|
async processRunOperation(item) {
|
|
1600
1623
|
clearTimeout(this.autoBatchTimeout);
|
|
1601
1624
|
this.autoBatchTimeout = undefined;
|
|
@@ -1752,7 +1775,7 @@ export class Client {
|
|
|
1752
1775
|
}).catch(console.error);
|
|
1753
1776
|
return;
|
|
1754
1777
|
}
|
|
1755
|
-
const mergedRunCreateParam =
|
|
1778
|
+
const mergedRunCreateParam = await this._mergeRuntimeEnvAndMaskMetadata(runCreate);
|
|
1756
1779
|
if (options?.apiKey !== undefined) {
|
|
1757
1780
|
headers["x-api-key"] = options.apiKey;
|
|
1758
1781
|
}
|
|
@@ -2941,7 +2964,7 @@ export class Client {
|
|
|
2941
2964
|
_hostUrl: this.getHostUrl(),
|
|
2942
2965
|
}));
|
|
2943
2966
|
}
|
|
2944
|
-
async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, }) {
|
|
2967
|
+
async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, tagValueIds = null, }) {
|
|
2945
2968
|
const upsert_ = upsert ? `?upsert=true` : "";
|
|
2946
2969
|
const endpoint = `${this.apiUrl}/sessions${upsert_}`;
|
|
2947
2970
|
const extra = projectExtra || {};
|
|
@@ -2965,6 +2988,9 @@ export class Client {
|
|
|
2965
2988
|
if (evaluatorKeys != null && evaluatorKeys.length > 0) {
|
|
2966
2989
|
body["evaluator_keys"] = evaluatorKeys;
|
|
2967
2990
|
}
|
|
2991
|
+
if (tagValueIds !== null) {
|
|
2992
|
+
body["tag_value_ids"] = tagValueIds;
|
|
2993
|
+
}
|
|
2968
2994
|
const serializedBody = JSON.stringify(body);
|
|
2969
2995
|
const response = await this.caller.call(async () => {
|
|
2970
2996
|
const res = await this._fetch(endpoint, {
|
|
@@ -3208,7 +3234,7 @@ export class Client {
|
|
|
3208
3234
|
const result = await response.json();
|
|
3209
3235
|
return result;
|
|
3210
3236
|
}
|
|
3211
|
-
async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, } = {}) {
|
|
3237
|
+
async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, tagValueIds, } = {}) {
|
|
3212
3238
|
const body = {
|
|
3213
3239
|
name,
|
|
3214
3240
|
description,
|
|
@@ -3223,6 +3249,9 @@ export class Client {
|
|
|
3223
3249
|
if (outputsSchema) {
|
|
3224
3250
|
body.outputs_schema_definition = outputsSchema;
|
|
3225
3251
|
}
|
|
3252
|
+
if (tagValueIds !== undefined) {
|
|
3253
|
+
body.tag_value_ids = tagValueIds;
|
|
3254
|
+
}
|
|
3226
3255
|
const serializedBody = JSON.stringify(body);
|
|
3227
3256
|
const response = await this.caller.call(async () => {
|
|
3228
3257
|
const res = await this._fetch(`${this.apiUrl}/datasets`, {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveVercelLsAgentType = resolveVercelLsAgentType;
|
|
4
|
+
exports.vercelLsAgentTypeMetadata = vercelLsAgentTypeMetadata;
|
|
5
|
+
const run_trees_js_1 = require("../../run_trees.cjs");
|
|
6
|
+
const traceable_js_1 = require("../../singletons/traceable.cjs");
|
|
7
|
+
const ls_agent_type_js_1 = require("../../utils/ls_agent_type.cjs");
|
|
8
|
+
// Vercel builds its traceable's `metadata` config eagerly, before traceable
|
|
9
|
+
// itself runs — this resolver stamps `ls_agent_type` at that moment.
|
|
10
|
+
// Traceable's own propagation would carry a parent's middleware/subagent/
|
|
11
|
+
// compaction/"root" tag down on its own. This resolver is needed
|
|
12
|
+
// for correct default tagging of the root `ls_agent_type` == root
|
|
13
|
+
// and tagging of subagents.
|
|
14
|
+
function resolveVercelLsAgentType(parentRunTree) {
|
|
15
|
+
const parent = parentRunTree ?? (0, traceable_js_1.getCurrentRunTree)(true);
|
|
16
|
+
if (!(0, run_trees_js_1.isRunTree)(parent))
|
|
17
|
+
return (0, ls_agent_type_js_1.resolveDefaultLsAgentType)(parent);
|
|
18
|
+
const parentTag = parent.extra?.metadata?.ls_agent_type;
|
|
19
|
+
if (typeof parentTag === "string" && ls_agent_type_js_1.NON_ROOT_LS_AGENT_TYPES.has(parentTag)) {
|
|
20
|
+
return parentTag;
|
|
21
|
+
}
|
|
22
|
+
if (parent.run_type === "tool")
|
|
23
|
+
return "subagent";
|
|
24
|
+
if (parentTag === "root")
|
|
25
|
+
return "root";
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
function vercelLsAgentTypeMetadata(parentRunTree) {
|
|
29
|
+
return (0, ls_agent_type_js_1.lsAgentTypeMetadata)(resolveVercelLsAgentType(parentRunTree));
|
|
30
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LsAgentType } from "../../utils/ls_agent_type.js";
|
|
2
|
+
export declare function resolveVercelLsAgentType(parentRunTree?: unknown): LsAgentType | undefined;
|
|
3
|
+
export declare function vercelLsAgentTypeMetadata(parentRunTree?: unknown): {
|
|
4
|
+
ls_agent_type?: LsAgentType;
|
|
5
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isRunTree } from "../../run_trees.js";
|
|
2
|
+
import { getCurrentRunTree } from "../../singletons/traceable.js";
|
|
3
|
+
import { NON_ROOT_LS_AGENT_TYPES, lsAgentTypeMetadata, resolveDefaultLsAgentType, } from "../../utils/ls_agent_type.js";
|
|
4
|
+
// Vercel builds its traceable's `metadata` config eagerly, before traceable
|
|
5
|
+
// itself runs — this resolver stamps `ls_agent_type` at that moment.
|
|
6
|
+
// Traceable's own propagation would carry a parent's middleware/subagent/
|
|
7
|
+
// compaction/"root" tag down on its own. This resolver is needed
|
|
8
|
+
// for correct default tagging of the root `ls_agent_type` == root
|
|
9
|
+
// and tagging of subagents.
|
|
10
|
+
export function resolveVercelLsAgentType(parentRunTree) {
|
|
11
|
+
const parent = parentRunTree ?? getCurrentRunTree(true);
|
|
12
|
+
if (!isRunTree(parent))
|
|
13
|
+
return resolveDefaultLsAgentType(parent);
|
|
14
|
+
const parentTag = parent.extra?.metadata?.ls_agent_type;
|
|
15
|
+
if (typeof parentTag === "string" && NON_ROOT_LS_AGENT_TYPES.has(parentTag)) {
|
|
16
|
+
return parentTag;
|
|
17
|
+
}
|
|
18
|
+
if (parent.run_type === "tool")
|
|
19
|
+
return "subagent";
|
|
20
|
+
if (parentTag === "root")
|
|
21
|
+
return "root";
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export function vercelLsAgentTypeMetadata(parentRunTree) {
|
|
25
|
+
return lsAgentTypeMetadata(resolveVercelLsAgentType(parentRunTree));
|
|
26
|
+
}
|
|
@@ -7,6 +7,7 @@ const env_js_1 = require("../../env.cjs");
|
|
|
7
7
|
const utils_js_1 = require("./utils.cjs");
|
|
8
8
|
const utils_js_2 = require("./utils.cjs");
|
|
9
9
|
const types_js_1 = require("../../utils/types.cjs");
|
|
10
|
+
const _agent_type_js_1 = require("./_agent_type.cjs");
|
|
10
11
|
function _formatMessages(messages) {
|
|
11
12
|
if (!Array.isArray(messages))
|
|
12
13
|
return messages;
|
|
@@ -52,12 +53,6 @@ event, traceRawHttp) {
|
|
|
52
53
|
}
|
|
53
54
|
return (0, utils_js_1.convertMessageToTracedFormat)(output);
|
|
54
55
|
}
|
|
55
|
-
function _getLsAgentType(parentRunTree) {
|
|
56
|
-
if ((0, run_trees_js_1.isRunTree)(parentRunTree) && parentRunTree.run_type === "tool") {
|
|
57
|
-
return "subagent";
|
|
58
|
-
}
|
|
59
|
-
return "root";
|
|
60
|
-
}
|
|
61
56
|
function _hasNonzeroUsageMetadata(runTree) {
|
|
62
57
|
const usageMetadata = runTree.extra?.metadata?.usage_metadata;
|
|
63
58
|
if (!(0, types_js_1.isRecord)(usageMetadata))
|
|
@@ -200,7 +195,7 @@ function LangSmithTelemetry(config) {
|
|
|
200
195
|
metadata: {
|
|
201
196
|
...customMetadata,
|
|
202
197
|
ai_sdk_method: event.operationId,
|
|
203
|
-
|
|
198
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(parentRunTree),
|
|
204
199
|
ls_model_name: event.modelId,
|
|
205
200
|
ls_integration: "vercel-ai-sdk-telemetry",
|
|
206
201
|
},
|
|
@@ -4,6 +4,7 @@ import { isEnvTracingEnabled } from "../../env.js";
|
|
|
4
4
|
import { convertMessageToTracedFormat } from "./utils.js";
|
|
5
5
|
import { setUsageMetadataOnRunTree } from "./utils.js";
|
|
6
6
|
import { isPrimitive, isRecord } from "../../utils/types.js";
|
|
7
|
+
import { vercelLsAgentTypeMetadata } from "./_agent_type.js";
|
|
7
8
|
function _formatMessages(messages) {
|
|
8
9
|
if (!Array.isArray(messages))
|
|
9
10
|
return messages;
|
|
@@ -49,12 +50,6 @@ event, traceRawHttp) {
|
|
|
49
50
|
}
|
|
50
51
|
return convertMessageToTracedFormat(output);
|
|
51
52
|
}
|
|
52
|
-
function _getLsAgentType(parentRunTree) {
|
|
53
|
-
if (isRunTree(parentRunTree) && parentRunTree.run_type === "tool") {
|
|
54
|
-
return "subagent";
|
|
55
|
-
}
|
|
56
|
-
return "root";
|
|
57
|
-
}
|
|
58
53
|
function _hasNonzeroUsageMetadata(runTree) {
|
|
59
54
|
const usageMetadata = runTree.extra?.metadata?.usage_metadata;
|
|
60
55
|
if (!isRecord(usageMetadata))
|
|
@@ -197,7 +192,7 @@ export function LangSmithTelemetry(config) {
|
|
|
197
192
|
metadata: {
|
|
198
193
|
...customMetadata,
|
|
199
194
|
ai_sdk_method: event.operationId,
|
|
200
|
-
|
|
195
|
+
...vercelLsAgentTypeMetadata(parentRunTree),
|
|
201
196
|
ls_model_name: event.modelId,
|
|
202
197
|
ls_integration: "vercel-ai-sdk-telemetry",
|
|
203
198
|
},
|
|
@@ -5,6 +5,7 @@ const middleware_js_1 = require("./middleware.cjs");
|
|
|
5
5
|
const utils_js_1 = require("./utils.cjs");
|
|
6
6
|
Object.defineProperty(exports, "convertMessageToTracedFormat", { enumerable: true, get: function () { return utils_js_1.convertMessageToTracedFormat; } });
|
|
7
7
|
const traceable_js_1 = require("../../traceable.cjs");
|
|
8
|
+
const _agent_type_js_1 = require("./_agent_type.cjs");
|
|
8
9
|
const _getModelDisplayName = (model) => {
|
|
9
10
|
if (typeof model === "string") {
|
|
10
11
|
return model;
|
|
@@ -118,19 +119,12 @@ const _resolveConfigs = (baseLsConfig, runtimeLsConfig) => {
|
|
|
118
119
|
resolvedToolConfig,
|
|
119
120
|
};
|
|
120
121
|
};
|
|
121
|
-
const _getLsAgentType = () => {
|
|
122
|
-
const parentRun = (0, traceable_js_1.getCurrentRunTree)(true);
|
|
123
|
-
if (parentRun != null && parentRun.run_type === "tool") {
|
|
124
|
-
return "subagent";
|
|
125
|
-
}
|
|
126
|
-
return "root";
|
|
127
|
-
};
|
|
128
122
|
const _getGenerateTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolvedLsConfig, hasExplicitOutput, hasExplicitExperimentalOutput, traceResponseMetadata, }) => {
|
|
129
123
|
return {
|
|
130
124
|
name: runName ?? _getModelDisplayName(model),
|
|
131
125
|
...resolvedLsConfig,
|
|
132
126
|
metadata: {
|
|
133
|
-
|
|
127
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
134
128
|
ai_sdk_method: aiSdkMethodName ?? "ai.generateText",
|
|
135
129
|
...resolvedLsConfig?.metadata,
|
|
136
130
|
},
|
|
@@ -206,7 +200,7 @@ const _getStreamTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolved
|
|
|
206
200
|
name: runName ?? _getModelDisplayName(model),
|
|
207
201
|
...resolvedLsConfig,
|
|
208
202
|
metadata: {
|
|
209
|
-
|
|
203
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
210
204
|
ai_sdk_method: aiSdkMethodName ?? "ai.streamText",
|
|
211
205
|
...resolvedLsConfig?.metadata,
|
|
212
206
|
},
|
|
@@ -409,7 +403,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
409
403
|
name: _getModelDisplayName(params.model),
|
|
410
404
|
...resolvedLsConfig,
|
|
411
405
|
metadata: {
|
|
412
|
-
|
|
406
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
413
407
|
ai_sdk_method: "ai.generateObject",
|
|
414
408
|
...resolvedLsConfig?.metadata,
|
|
415
409
|
},
|
|
@@ -531,7 +525,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
531
525
|
name: _getModelDisplayName(params.model),
|
|
532
526
|
...resolvedLsConfig,
|
|
533
527
|
metadata: {
|
|
534
|
-
|
|
528
|
+
...(0, _agent_type_js_1.vercelLsAgentTypeMetadata)(),
|
|
535
529
|
ai_sdk_method: "ai.streamObject",
|
|
536
530
|
...resolvedLsConfig?.metadata,
|
|
537
531
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LangSmithMiddleware, } from "./middleware.js";
|
|
2
2
|
import { convertMessageToTracedFormat } from "./utils.js";
|
|
3
|
-
import { isTraceableFunction, traceable
|
|
3
|
+
import { isTraceableFunction, traceable } from "../../traceable.js";
|
|
4
|
+
import { vercelLsAgentTypeMetadata } from "./_agent_type.js";
|
|
4
5
|
const _getModelDisplayName = (model) => {
|
|
5
6
|
if (typeof model === "string") {
|
|
6
7
|
return model;
|
|
@@ -114,19 +115,12 @@ const _resolveConfigs = (baseLsConfig, runtimeLsConfig) => {
|
|
|
114
115
|
resolvedToolConfig,
|
|
115
116
|
};
|
|
116
117
|
};
|
|
117
|
-
const _getLsAgentType = () => {
|
|
118
|
-
const parentRun = getCurrentRunTree(true);
|
|
119
|
-
if (parentRun != null && parentRun.run_type === "tool") {
|
|
120
|
-
return "subagent";
|
|
121
|
-
}
|
|
122
|
-
return "root";
|
|
123
|
-
};
|
|
124
118
|
const _getGenerateTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolvedLsConfig, hasExplicitOutput, hasExplicitExperimentalOutput, traceResponseMetadata, }) => {
|
|
125
119
|
return {
|
|
126
120
|
name: runName ?? _getModelDisplayName(model),
|
|
127
121
|
...resolvedLsConfig,
|
|
128
122
|
metadata: {
|
|
129
|
-
|
|
123
|
+
...vercelLsAgentTypeMetadata(),
|
|
130
124
|
ai_sdk_method: aiSdkMethodName ?? "ai.generateText",
|
|
131
125
|
...resolvedLsConfig?.metadata,
|
|
132
126
|
},
|
|
@@ -202,7 +196,7 @@ const _getStreamTextWrapperConfig = ({ model, runName, aiSdkMethodName, resolved
|
|
|
202
196
|
name: runName ?? _getModelDisplayName(model),
|
|
203
197
|
...resolvedLsConfig,
|
|
204
198
|
metadata: {
|
|
205
|
-
|
|
199
|
+
...vercelLsAgentTypeMetadata(),
|
|
206
200
|
ai_sdk_method: aiSdkMethodName ?? "ai.streamText",
|
|
207
201
|
...resolvedLsConfig?.metadata,
|
|
208
202
|
},
|
|
@@ -404,7 +398,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
404
398
|
name: _getModelDisplayName(params.model),
|
|
405
399
|
...resolvedLsConfig,
|
|
406
400
|
metadata: {
|
|
407
|
-
|
|
401
|
+
...vercelLsAgentTypeMetadata(),
|
|
408
402
|
ai_sdk_method: "ai.generateObject",
|
|
409
403
|
...resolvedLsConfig?.metadata,
|
|
410
404
|
},
|
|
@@ -526,7 +520,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
526
520
|
name: _getModelDisplayName(params.model),
|
|
527
521
|
...resolvedLsConfig,
|
|
528
522
|
metadata: {
|
|
529
|
-
|
|
523
|
+
...vercelLsAgentTypeMetadata(),
|
|
530
524
|
ai_sdk_method: "ai.streamObject",
|
|
531
525
|
...resolvedLsConfig?.metadata,
|
|
532
526
|
},
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,6 @@ Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, g
|
|
|
35
35
|
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return error_js_1.RateLimitError; } });
|
|
36
36
|
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return error_js_1.InternalServerError; } });
|
|
37
37
|
// Update using pnpm bump-version
|
|
38
|
-
exports.__version__ = "0.8.
|
|
38
|
+
exports.__version__ = "0.8.10";
|
|
39
39
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
40
40
|
exports.LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export { computeRunIdForSecondaryReplica, uuid7, uuid7FromTime, } from "./uuid.j
|
|
|
7
7
|
export { isTracingEnabled } from "./utils/guard.js";
|
|
8
8
|
export { Cache, PromptCache, type CacheConfig, type CacheMetrics, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
9
9
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
10
|
-
export declare const __version__ = "0.8.
|
|
10
|
+
export declare const __version__ = "0.8.10";
|
|
11
11
|
export declare const LS_MESSAGE_VIEW_EXCLUDE: "ls_message_view_exclude";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,6 @@ export { isTracingEnabled } from "./utils/guard.js";
|
|
|
7
7
|
export { Cache, PromptCache, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
8
8
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
9
9
|
// Update using pnpm bump-version
|
|
10
|
-
export const __version__ = "0.8.
|
|
10
|
+
export const __version__ = "0.8.10";
|
|
11
11
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
12
12
|
export const LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
package/dist/utils/_git.cjs
CHANGED
|
@@ -17,6 +17,33 @@ const execGit = (command, exec) => {
|
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
};
|
|
20
|
+
function sanitizeRemoteUrl(remoteUrl) {
|
|
21
|
+
if (remoteUrl == null) {
|
|
22
|
+
return remoteUrl;
|
|
23
|
+
}
|
|
24
|
+
const schemeSeparator = remoteUrl.indexOf("://");
|
|
25
|
+
if (schemeSeparator === -1) {
|
|
26
|
+
return remoteUrl;
|
|
27
|
+
}
|
|
28
|
+
const scheme = remoteUrl.slice(0, schemeSeparator).toLowerCase();
|
|
29
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
30
|
+
return remoteUrl;
|
|
31
|
+
}
|
|
32
|
+
const authorityStart = schemeSeparator + "://".length;
|
|
33
|
+
let authorityEnd = remoteUrl.length;
|
|
34
|
+
for (const delimiter of ["/", "?", "#"]) {
|
|
35
|
+
const delimiterIndex = remoteUrl.indexOf(delimiter, authorityStart);
|
|
36
|
+
if (delimiterIndex !== -1) {
|
|
37
|
+
authorityEnd = Math.min(authorityEnd, delimiterIndex);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const authority = remoteUrl.slice(authorityStart, authorityEnd);
|
|
41
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
42
|
+
if (userinfoEnd === -1) {
|
|
43
|
+
return remoteUrl;
|
|
44
|
+
}
|
|
45
|
+
return `${remoteUrl.slice(0, authorityStart)}${authority.slice(userinfoEnd + 1)}${remoteUrl.slice(authorityEnd)}`;
|
|
46
|
+
}
|
|
20
47
|
const getGitInfo = async (remote = "origin") => {
|
|
21
48
|
let exec;
|
|
22
49
|
try {
|
|
@@ -42,7 +69,7 @@ const getGitInfo = async (remote = "origin") => {
|
|
|
42
69
|
execGit(["log", "-1", "--format=%ae"], exec),
|
|
43
70
|
]);
|
|
44
71
|
return {
|
|
45
|
-
remoteUrl,
|
|
72
|
+
remoteUrl: sanitizeRemoteUrl(remoteUrl),
|
|
46
73
|
commit,
|
|
47
74
|
commitTime,
|
|
48
75
|
branch,
|
package/dist/utils/_git.js
CHANGED
|
@@ -14,6 +14,33 @@ const execGit = (command, exec) => {
|
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
|
+
function sanitizeRemoteUrl(remoteUrl) {
|
|
18
|
+
if (remoteUrl == null) {
|
|
19
|
+
return remoteUrl;
|
|
20
|
+
}
|
|
21
|
+
const schemeSeparator = remoteUrl.indexOf("://");
|
|
22
|
+
if (schemeSeparator === -1) {
|
|
23
|
+
return remoteUrl;
|
|
24
|
+
}
|
|
25
|
+
const scheme = remoteUrl.slice(0, schemeSeparator).toLowerCase();
|
|
26
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
27
|
+
return remoteUrl;
|
|
28
|
+
}
|
|
29
|
+
const authorityStart = schemeSeparator + "://".length;
|
|
30
|
+
let authorityEnd = remoteUrl.length;
|
|
31
|
+
for (const delimiter of ["/", "?", "#"]) {
|
|
32
|
+
const delimiterIndex = remoteUrl.indexOf(delimiter, authorityStart);
|
|
33
|
+
if (delimiterIndex !== -1) {
|
|
34
|
+
authorityEnd = Math.min(authorityEnd, delimiterIndex);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const authority = remoteUrl.slice(authorityStart, authorityEnd);
|
|
38
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
39
|
+
if (userinfoEnd === -1) {
|
|
40
|
+
return remoteUrl;
|
|
41
|
+
}
|
|
42
|
+
return `${remoteUrl.slice(0, authorityStart)}${authority.slice(userinfoEnd + 1)}${remoteUrl.slice(authorityEnd)}`;
|
|
43
|
+
}
|
|
17
44
|
export const getGitInfo = async (remote = "origin") => {
|
|
18
45
|
let exec;
|
|
19
46
|
try {
|
|
@@ -39,7 +66,7 @@ export const getGitInfo = async (remote = "origin") => {
|
|
|
39
66
|
execGit(["log", "-1", "--format=%ae"], exec),
|
|
40
67
|
]);
|
|
41
68
|
return {
|
|
42
|
-
remoteUrl,
|
|
69
|
+
remoteUrl: sanitizeRemoteUrl(remoteUrl),
|
|
43
70
|
commit,
|
|
44
71
|
commitTime,
|
|
45
72
|
branch,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shared primitives for the `ls_agent_type` metadata tag.
|
|
3
|
+
// Consumed by wrappers/integrations that stamp or inspect `ls_agent_type` on
|
|
4
|
+
// traced runs (wrap_openai, OpenAI Agents SDK, Vercel, future wrappers).
|
|
5
|
+
// Keep this module SDK-agnostic: the caller passes in the parent run tree.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.NON_ROOT_LS_AGENT_TYPES = void 0;
|
|
8
|
+
exports.resolveDefaultLsAgentType = resolveDefaultLsAgentType;
|
|
9
|
+
exports.lsAgentTypeMetadata = lsAgentTypeMetadata;
|
|
10
|
+
exports.defaultLsAgentTypeMetadata = defaultLsAgentTypeMetadata;
|
|
11
|
+
const run_trees_js_1 = require("../run_trees.cjs");
|
|
12
|
+
// Non-root tags: preserved against default/structural stamping.
|
|
13
|
+
exports.NON_ROOT_LS_AGENT_TYPES = new Set([
|
|
14
|
+
"middleware",
|
|
15
|
+
"subagent",
|
|
16
|
+
"compaction",
|
|
17
|
+
]);
|
|
18
|
+
// `"root"` at trace root; `undefined` when nested (rely on propagation).
|
|
19
|
+
function resolveDefaultLsAgentType(parentRunTree) {
|
|
20
|
+
return (0, run_trees_js_1.isRunTree)(parentRunTree) ? undefined : "root";
|
|
21
|
+
}
|
|
22
|
+
// Spread helper: `{ ls_agent_type: tag }` when tag is set, `{}` when undefined.
|
|
23
|
+
function lsAgentTypeMetadata(tag) {
|
|
24
|
+
return tag !== undefined ? { ls_agent_type: tag } : {};
|
|
25
|
+
}
|
|
26
|
+
// Preserves user-supplied ls_agent_type; stamps default only when key is absent.
|
|
27
|
+
function defaultLsAgentTypeMetadata(existingMetadata, parentRunTree) {
|
|
28
|
+
if ("ls_agent_type" in existingMetadata)
|
|
29
|
+
return {};
|
|
30
|
+
return lsAgentTypeMetadata(resolveDefaultLsAgentType(parentRunTree));
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type LsAgentType = "root" | "middleware" | "subagent" | "compaction";
|
|
2
|
+
export declare const NON_ROOT_LS_AGENT_TYPES: ReadonlySet<string>;
|
|
3
|
+
export declare function resolveDefaultLsAgentType(parentRunTree?: unknown): LsAgentType | undefined;
|
|
4
|
+
export declare function lsAgentTypeMetadata(tag: LsAgentType | undefined): {
|
|
5
|
+
ls_agent_type?: LsAgentType;
|
|
6
|
+
};
|
|
7
|
+
export declare function defaultLsAgentTypeMetadata(existingMetadata: Record<string, unknown>, parentRunTree?: unknown): {
|
|
8
|
+
ls_agent_type?: LsAgentType;
|
|
9
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Shared primitives for the `ls_agent_type` metadata tag.
|
|
2
|
+
// Consumed by wrappers/integrations that stamp or inspect `ls_agent_type` on
|
|
3
|
+
// traced runs (wrap_openai, OpenAI Agents SDK, Vercel, future wrappers).
|
|
4
|
+
// Keep this module SDK-agnostic: the caller passes in the parent run tree.
|
|
5
|
+
import { isRunTree } from "../run_trees.js";
|
|
6
|
+
// Non-root tags: preserved against default/structural stamping.
|
|
7
|
+
export const NON_ROOT_LS_AGENT_TYPES = new Set([
|
|
8
|
+
"middleware",
|
|
9
|
+
"subagent",
|
|
10
|
+
"compaction",
|
|
11
|
+
]);
|
|
12
|
+
// `"root"` at trace root; `undefined` when nested (rely on propagation).
|
|
13
|
+
export function resolveDefaultLsAgentType(parentRunTree) {
|
|
14
|
+
return isRunTree(parentRunTree) ? undefined : "root";
|
|
15
|
+
}
|
|
16
|
+
// Spread helper: `{ ls_agent_type: tag }` when tag is set, `{}` when undefined.
|
|
17
|
+
export function lsAgentTypeMetadata(tag) {
|
|
18
|
+
return tag !== undefined ? { ls_agent_type: tag } : {};
|
|
19
|
+
}
|
|
20
|
+
// Preserves user-supplied ls_agent_type; stamps default only when key is absent.
|
|
21
|
+
export function defaultLsAgentTypeMetadata(existingMetadata, parentRunTree) {
|
|
22
|
+
if ("ls_agent_type" in existingMetadata)
|
|
23
|
+
return {};
|
|
24
|
+
return lsAgentTypeMetadata(resolveDefaultLsAgentType(parentRunTree));
|
|
25
|
+
}
|
package/dist/utils/profiles.cjs
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ProfileAuth = exports.DEFAULT_API_URL = void 0;
|
|
37
37
|
exports.hasValue = hasValue;
|
|
38
|
+
exports.resolveTokenEndpoint = resolveTokenEndpoint;
|
|
38
39
|
exports.loadProfileClientConfig = loadProfileClientConfig;
|
|
39
40
|
const env_js_1 = require("./env.cjs");
|
|
40
41
|
const fsUtils = __importStar(require("./fs.cjs"));
|
|
@@ -43,6 +44,8 @@ exports.DEFAULT_API_URL = "https://api.smith.langchain.com";
|
|
|
43
44
|
const OAUTH_CLIENT_ID = "langsmith-cli";
|
|
44
45
|
const TOKEN_REFRESH_LEEWAY_MS = 60_000;
|
|
45
46
|
const TOKEN_REFRESH_TIMEOUT_MS = 10_000;
|
|
47
|
+
const OAUTH_DISCOVERY_TIMEOUT_MS = 5_000;
|
|
48
|
+
const WELL_KNOWN_OAUTH_PATH = "/.well-known/oauth-authorization-server";
|
|
46
49
|
function isBrowserLikeRuntime() {
|
|
47
50
|
const env = (0, env_js_1.getEnv)();
|
|
48
51
|
return env === "browser" || env === "webworker";
|
|
@@ -125,6 +128,126 @@ function normalizeConfigUrl(apiUrl) {
|
|
|
125
128
|
? normalized.slice(0, -apiV1Suffix.length)
|
|
126
129
|
: normalized;
|
|
127
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Metadata base URLs to probe, most specific first: the configured mount point,
|
|
133
|
+
* then the self-hosted and SaaS locations, so both a bare origin and an
|
|
134
|
+
* explicit `/api` resolve.
|
|
135
|
+
*/
|
|
136
|
+
function oauthDiscoveryCandidates(apiUrl) {
|
|
137
|
+
const given = normalizeConfigUrl(apiUrl);
|
|
138
|
+
const origin = given.endsWith("/api")
|
|
139
|
+
? given.slice(0, -"/api".length)
|
|
140
|
+
: given;
|
|
141
|
+
const candidates = [];
|
|
142
|
+
for (const candidate of [given, `${origin}/api`, origin]) {
|
|
143
|
+
if (candidate && candidate !== "/api" && !candidates.includes(candidate)) {
|
|
144
|
+
candidates.push(candidate);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return candidates;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check the document describes the deployment we probed. RFC 8414 requires the
|
|
151
|
+
* issuer to match the URL the well-known path was built from, and every
|
|
152
|
+
* endpoint must share the issuer's origin. Refresh tokens are posted to these
|
|
153
|
+
* endpoints, so an unvalidated document could redirect credentials elsewhere.
|
|
154
|
+
*/
|
|
155
|
+
function isTrustedOAuthMetadata(doc, base) {
|
|
156
|
+
const { issuer } = doc;
|
|
157
|
+
if (typeof issuer !== "string" ||
|
|
158
|
+
issuer.replace(/\/+$/, "") !== base.replace(/\/+$/, "")) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
let issuerUrl;
|
|
162
|
+
try {
|
|
163
|
+
issuerUrl = new URL(issuer);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
for (const endpoint of [
|
|
169
|
+
doc.device_authorization_endpoint,
|
|
170
|
+
doc.token_endpoint,
|
|
171
|
+
]) {
|
|
172
|
+
if (typeof endpoint !== "string" || !endpoint) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const url = new URL(endpoint);
|
|
177
|
+
if (url.protocol !== issuerUrl.protocol || url.host !== issuerUrl.host) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Metadata URLs for an issuer, RFC 8414 form first. RFC 8414 inserts the
|
|
189
|
+
* well-known segment between the origin and the issuer path, so
|
|
190
|
+
* `https://host/api` is described at
|
|
191
|
+
* `https://host/.well-known/oauth-authorization-server/api`. Deployments
|
|
192
|
+
* commonly also serve the appended form, and for a path-less issuer the two are
|
|
193
|
+
* identical.
|
|
194
|
+
*/
|
|
195
|
+
function oauthMetadataUrls(base) {
|
|
196
|
+
const appended = `${base}${WELL_KNOWN_OAUTH_PATH}`;
|
|
197
|
+
let inserted;
|
|
198
|
+
try {
|
|
199
|
+
const url = new URL(base);
|
|
200
|
+
inserted = `${url.origin}${WELL_KNOWN_OAUTH_PATH}${url.pathname === "/" ? "" : url.pathname}`;
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return [appended];
|
|
204
|
+
}
|
|
205
|
+
return inserted === appended ? [inserted] : [inserted, appended];
|
|
206
|
+
}
|
|
207
|
+
async function fetchOAuthMetadata(url, base, fetchImplementation) {
|
|
208
|
+
let response;
|
|
209
|
+
try {
|
|
210
|
+
response = await fetchImplementation(url, {
|
|
211
|
+
method: "GET",
|
|
212
|
+
headers: { Accept: "application/json" },
|
|
213
|
+
signal: AbortSignal.timeout(OAUTH_DISCOVERY_TIMEOUT_MS),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
let doc;
|
|
223
|
+
try {
|
|
224
|
+
// Self-hosted answers unknown paths with an HTML 200 from the SPA.
|
|
225
|
+
doc = (await response.json());
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
if (!doc || typeof doc !== "object" || !isTrustedOAuthMetadata(doc, base)) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
return doc;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
237
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
238
|
+
* self-hosted mounts the authorization server under it.
|
|
239
|
+
*/
|
|
240
|
+
async function resolveTokenEndpoint(apiUrl, fetchImplementation) {
|
|
241
|
+
for (const base of oauthDiscoveryCandidates(apiUrl)) {
|
|
242
|
+
for (const url of oauthMetadataUrls(base)) {
|
|
243
|
+
const doc = await fetchOAuthMetadata(url, base, fetchImplementation);
|
|
244
|
+
if (doc) {
|
|
245
|
+
return doc.token_endpoint;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return `${normalizeConfigUrl(apiUrl)}/oauth/token`;
|
|
250
|
+
}
|
|
128
251
|
function applyTokenResponse(profile, token) {
|
|
129
252
|
profile.oauth ??= {};
|
|
130
253
|
if (token.access_token) {
|
|
@@ -262,7 +385,8 @@ class ProfileAuth {
|
|
|
262
385
|
client_id: OAUTH_CLIENT_ID,
|
|
263
386
|
refresh_token: this.state.profile.oauth?.refresh_token ?? refreshToken,
|
|
264
387
|
});
|
|
265
|
-
const
|
|
388
|
+
const tokenEndpoint = await resolveTokenEndpoint(refreshApiUrl, fetchImplementation);
|
|
389
|
+
const response = await fetchImplementation(tokenEndpoint, {
|
|
266
390
|
method: "POST",
|
|
267
391
|
headers: {
|
|
268
392
|
"Content-Type": "application/x-www-form-urlencoded",
|
package/dist/utils/profiles.d.ts
CHANGED
|
@@ -33,6 +33,12 @@ export type ProfileClientConfig = {
|
|
|
33
33
|
profileAuth?: ProfileAuth;
|
|
34
34
|
};
|
|
35
35
|
export declare function hasValue(value?: string | null): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
38
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
39
|
+
* self-hosted mounts the authorization server under it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveTokenEndpoint(apiUrl: string, fetchImplementation: typeof fetch): Promise<string>;
|
|
36
42
|
export declare function loadProfileClientConfig(): ProfileClientConfig;
|
|
37
43
|
export declare class ProfileAuth {
|
|
38
44
|
private state;
|
package/dist/utils/profiles.js
CHANGED
|
@@ -5,6 +5,8 @@ export const DEFAULT_API_URL = "https://api.smith.langchain.com";
|
|
|
5
5
|
const OAUTH_CLIENT_ID = "langsmith-cli";
|
|
6
6
|
const TOKEN_REFRESH_LEEWAY_MS = 60_000;
|
|
7
7
|
const TOKEN_REFRESH_TIMEOUT_MS = 10_000;
|
|
8
|
+
const OAUTH_DISCOVERY_TIMEOUT_MS = 5_000;
|
|
9
|
+
const WELL_KNOWN_OAUTH_PATH = "/.well-known/oauth-authorization-server";
|
|
8
10
|
function isBrowserLikeRuntime() {
|
|
9
11
|
const env = getEnv();
|
|
10
12
|
return env === "browser" || env === "webworker";
|
|
@@ -87,6 +89,126 @@ function normalizeConfigUrl(apiUrl) {
|
|
|
87
89
|
? normalized.slice(0, -apiV1Suffix.length)
|
|
88
90
|
: normalized;
|
|
89
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Metadata base URLs to probe, most specific first: the configured mount point,
|
|
94
|
+
* then the self-hosted and SaaS locations, so both a bare origin and an
|
|
95
|
+
* explicit `/api` resolve.
|
|
96
|
+
*/
|
|
97
|
+
function oauthDiscoveryCandidates(apiUrl) {
|
|
98
|
+
const given = normalizeConfigUrl(apiUrl);
|
|
99
|
+
const origin = given.endsWith("/api")
|
|
100
|
+
? given.slice(0, -"/api".length)
|
|
101
|
+
: given;
|
|
102
|
+
const candidates = [];
|
|
103
|
+
for (const candidate of [given, `${origin}/api`, origin]) {
|
|
104
|
+
if (candidate && candidate !== "/api" && !candidates.includes(candidate)) {
|
|
105
|
+
candidates.push(candidate);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return candidates;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check the document describes the deployment we probed. RFC 8414 requires the
|
|
112
|
+
* issuer to match the URL the well-known path was built from, and every
|
|
113
|
+
* endpoint must share the issuer's origin. Refresh tokens are posted to these
|
|
114
|
+
* endpoints, so an unvalidated document could redirect credentials elsewhere.
|
|
115
|
+
*/
|
|
116
|
+
function isTrustedOAuthMetadata(doc, base) {
|
|
117
|
+
const { issuer } = doc;
|
|
118
|
+
if (typeof issuer !== "string" ||
|
|
119
|
+
issuer.replace(/\/+$/, "") !== base.replace(/\/+$/, "")) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
let issuerUrl;
|
|
123
|
+
try {
|
|
124
|
+
issuerUrl = new URL(issuer);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
for (const endpoint of [
|
|
130
|
+
doc.device_authorization_endpoint,
|
|
131
|
+
doc.token_endpoint,
|
|
132
|
+
]) {
|
|
133
|
+
if (typeof endpoint !== "string" || !endpoint) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const url = new URL(endpoint);
|
|
138
|
+
if (url.protocol !== issuerUrl.protocol || url.host !== issuerUrl.host) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Metadata URLs for an issuer, RFC 8414 form first. RFC 8414 inserts the
|
|
150
|
+
* well-known segment between the origin and the issuer path, so
|
|
151
|
+
* `https://host/api` is described at
|
|
152
|
+
* `https://host/.well-known/oauth-authorization-server/api`. Deployments
|
|
153
|
+
* commonly also serve the appended form, and for a path-less issuer the two are
|
|
154
|
+
* identical.
|
|
155
|
+
*/
|
|
156
|
+
function oauthMetadataUrls(base) {
|
|
157
|
+
const appended = `${base}${WELL_KNOWN_OAUTH_PATH}`;
|
|
158
|
+
let inserted;
|
|
159
|
+
try {
|
|
160
|
+
const url = new URL(base);
|
|
161
|
+
inserted = `${url.origin}${WELL_KNOWN_OAUTH_PATH}${url.pathname === "/" ? "" : url.pathname}`;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return [appended];
|
|
165
|
+
}
|
|
166
|
+
return inserted === appended ? [inserted] : [inserted, appended];
|
|
167
|
+
}
|
|
168
|
+
async function fetchOAuthMetadata(url, base, fetchImplementation) {
|
|
169
|
+
let response;
|
|
170
|
+
try {
|
|
171
|
+
response = await fetchImplementation(url, {
|
|
172
|
+
method: "GET",
|
|
173
|
+
headers: { Accept: "application/json" },
|
|
174
|
+
signal: AbortSignal.timeout(OAUTH_DISCOVERY_TIMEOUT_MS),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
let doc;
|
|
184
|
+
try {
|
|
185
|
+
// Self-hosted answers unknown paths with an HTML 200 from the SPA.
|
|
186
|
+
doc = (await response.json());
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
if (!doc || typeof doc !== "object" || !isTrustedOAuthMetadata(doc, base)) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
return doc;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
198
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
199
|
+
* self-hosted mounts the authorization server under it.
|
|
200
|
+
*/
|
|
201
|
+
export async function resolveTokenEndpoint(apiUrl, fetchImplementation) {
|
|
202
|
+
for (const base of oauthDiscoveryCandidates(apiUrl)) {
|
|
203
|
+
for (const url of oauthMetadataUrls(base)) {
|
|
204
|
+
const doc = await fetchOAuthMetadata(url, base, fetchImplementation);
|
|
205
|
+
if (doc) {
|
|
206
|
+
return doc.token_endpoint;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return `${normalizeConfigUrl(apiUrl)}/oauth/token`;
|
|
211
|
+
}
|
|
90
212
|
function applyTokenResponse(profile, token) {
|
|
91
213
|
profile.oauth ??= {};
|
|
92
214
|
if (token.access_token) {
|
|
@@ -224,7 +346,8 @@ export class ProfileAuth {
|
|
|
224
346
|
client_id: OAUTH_CLIENT_ID,
|
|
225
347
|
refresh_token: this.state.profile.oauth?.refresh_token ?? refreshToken,
|
|
226
348
|
});
|
|
227
|
-
const
|
|
349
|
+
const tokenEndpoint = await resolveTokenEndpoint(refreshApiUrl, fetchImplementation);
|
|
350
|
+
const response = await fetchImplementation(tokenEndpoint, {
|
|
228
351
|
method: "POST",
|
|
229
352
|
headers: {
|
|
230
353
|
"Content-Type": "application/x-www-form-urlencoded",
|
package/dist/wrappers/openai.cjs
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapOpenAI = void 0;
|
|
4
4
|
const traceable_js_1 = require("../traceable.cjs");
|
|
5
|
+
const traceable_js_2 = require("../singletons/traceable.cjs");
|
|
6
|
+
const ls_agent_type_js_1 = require("../utils/ls_agent_type.cjs");
|
|
5
7
|
const TRACED_INVOCATION_KEYS = [
|
|
6
8
|
"frequency_penalty",
|
|
7
9
|
"n",
|
|
@@ -261,6 +263,7 @@ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams,
|
|
|
261
263
|
...prepopulatedInvocationParams,
|
|
262
264
|
...ls_invocation_params,
|
|
263
265
|
},
|
|
266
|
+
...(0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)(requestMetadata, (0, traceable_js_2.getCurrentRunTree)(true)),
|
|
264
267
|
};
|
|
265
268
|
};
|
|
266
269
|
};
|
|
@@ -416,6 +419,7 @@ const wrapOpenAI = (openai, options) => {
|
|
|
416
419
|
...prepopulatedInvocationParams,
|
|
417
420
|
...ls_invocation_params,
|
|
418
421
|
},
|
|
422
|
+
...(0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)({}, (0, traceable_js_2.getCurrentRunTree)(true)),
|
|
419
423
|
};
|
|
420
424
|
},
|
|
421
425
|
...cleanedOptions,
|
package/dist/wrappers/openai.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isTraceableFunction, traceable, } from "../traceable.js";
|
|
2
|
+
import { getCurrentRunTree } from "../singletons/traceable.js";
|
|
3
|
+
import { defaultLsAgentTypeMetadata } from "../utils/ls_agent_type.js";
|
|
2
4
|
const TRACED_INVOCATION_KEYS = [
|
|
3
5
|
"frequency_penalty",
|
|
4
6
|
"n",
|
|
@@ -258,6 +260,7 @@ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams,
|
|
|
258
260
|
...prepopulatedInvocationParams,
|
|
259
261
|
...ls_invocation_params,
|
|
260
262
|
},
|
|
263
|
+
...defaultLsAgentTypeMetadata(requestMetadata, getCurrentRunTree(true)),
|
|
261
264
|
};
|
|
262
265
|
};
|
|
263
266
|
};
|
|
@@ -413,6 +416,7 @@ export const wrapOpenAI = (openai, options) => {
|
|
|
413
416
|
...prepopulatedInvocationParams,
|
|
414
417
|
...ls_invocation_params,
|
|
415
418
|
},
|
|
419
|
+
...defaultLsAgentTypeMetadata({}, getCurrentRunTree(true)),
|
|
416
420
|
};
|
|
417
421
|
},
|
|
418
422
|
...cleanedOptions,
|
|
@@ -10,6 +10,7 @@ const node_async_hooks_1 = require("node:async_hooks");
|
|
|
10
10
|
const run_trees_js_1 = require("../run_trees.cjs");
|
|
11
11
|
const client_js_1 = require("../client.cjs");
|
|
12
12
|
const traceable_js_1 = require("../singletons/traceable.cjs");
|
|
13
|
+
const ls_agent_type_js_1 = require("../utils/ls_agent_type.cjs");
|
|
13
14
|
traceable_js_1.AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new node_async_hooks_1.AsyncLocalStorage());
|
|
14
15
|
/**
|
|
15
16
|
* Set the current AsyncLocalStorage store to the given RunTree without a
|
|
@@ -521,14 +522,15 @@ class OpenAIAgentsTracingProcessor {
|
|
|
521
522
|
else {
|
|
522
523
|
runName = "Agent workflow";
|
|
523
524
|
}
|
|
524
|
-
//
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
},
|
|
525
|
+
// Merge three sources: processor defaults, trace.metadata (user's per-run
|
|
526
|
+
// ls_agent_type), and force-set ls_integration.
|
|
527
|
+
const mergedMetadata = {
|
|
528
|
+
...this._metadata,
|
|
529
|
+
...(trace.metadata ?? {}),
|
|
530
|
+
ls_integration: "openai-agents-sdk",
|
|
531
531
|
};
|
|
532
|
+
Object.assign(mergedMetadata, (0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)(mergedMetadata, currentRunTree));
|
|
533
|
+
const runExtra = { metadata: mergedMetadata };
|
|
532
534
|
const traceDict = trace.toJSON() ?? {};
|
|
533
535
|
const groupId = trace.groupId ??
|
|
534
536
|
traceDict.groupId ??
|
|
@@ -589,9 +591,10 @@ class OpenAIAgentsTracingProcessor {
|
|
|
589
591
|
}
|
|
590
592
|
this._runs.delete(trace.traceId);
|
|
591
593
|
const traceDict = trace.toJSON() ?? {};
|
|
594
|
+
// trace.metadata may have new keys since onTraceStart; pull them in.
|
|
592
595
|
const metadata = {
|
|
593
|
-
...traceDict.metadata,
|
|
594
596
|
...this._metadata,
|
|
597
|
+
...traceDict.metadata,
|
|
595
598
|
};
|
|
596
599
|
try {
|
|
597
600
|
// Update run with final inputs/outputs
|
|
@@ -695,10 +698,10 @@ class OpenAIAgentsTracingProcessor {
|
|
|
695
698
|
if (!childRun.extra.metadata) {
|
|
696
699
|
childRun.extra.metadata = {};
|
|
697
700
|
}
|
|
698
|
-
childRun.extra.metadata
|
|
699
|
-
|
|
700
|
-
ls_agent_type
|
|
701
|
-
}
|
|
701
|
+
const meta = childRun.extra.metadata;
|
|
702
|
+
if (!ls_agent_type_js_1.NON_ROOT_LS_AGENT_TYPES.has(meta.ls_agent_type)) {
|
|
703
|
+
meta.ls_agent_type = "subagent";
|
|
704
|
+
}
|
|
702
705
|
}
|
|
703
706
|
}
|
|
704
707
|
// Track span data type for parent lookups
|
|
@@ -7,6 +7,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
7
7
|
import { RunTree } from "../run_trees.js";
|
|
8
8
|
import { Client } from "../client.js";
|
|
9
9
|
import { AsyncLocalStorageProviderSingleton, getCurrentRunTree, } from "../singletons/traceable.js";
|
|
10
|
+
import { NON_ROOT_LS_AGENT_TYPES, defaultLsAgentTypeMetadata, } from "../utils/ls_agent_type.js";
|
|
10
11
|
AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new AsyncLocalStorage());
|
|
11
12
|
/**
|
|
12
13
|
* Set the current AsyncLocalStorage store to the given RunTree without a
|
|
@@ -518,14 +519,15 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
518
519
|
else {
|
|
519
520
|
runName = "Agent workflow";
|
|
520
521
|
}
|
|
521
|
-
//
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
},
|
|
522
|
+
// Merge three sources: processor defaults, trace.metadata (user's per-run
|
|
523
|
+
// ls_agent_type), and force-set ls_integration.
|
|
524
|
+
const mergedMetadata = {
|
|
525
|
+
...this._metadata,
|
|
526
|
+
...(trace.metadata ?? {}),
|
|
527
|
+
ls_integration: "openai-agents-sdk",
|
|
528
528
|
};
|
|
529
|
+
Object.assign(mergedMetadata, defaultLsAgentTypeMetadata(mergedMetadata, currentRunTree));
|
|
530
|
+
const runExtra = { metadata: mergedMetadata };
|
|
529
531
|
const traceDict = trace.toJSON() ?? {};
|
|
530
532
|
const groupId = trace.groupId ??
|
|
531
533
|
traceDict.groupId ??
|
|
@@ -586,9 +588,10 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
586
588
|
}
|
|
587
589
|
this._runs.delete(trace.traceId);
|
|
588
590
|
const traceDict = trace.toJSON() ?? {};
|
|
591
|
+
// trace.metadata may have new keys since onTraceStart; pull them in.
|
|
589
592
|
const metadata = {
|
|
590
|
-
...traceDict.metadata,
|
|
591
593
|
...this._metadata,
|
|
594
|
+
...traceDict.metadata,
|
|
592
595
|
};
|
|
593
596
|
try {
|
|
594
597
|
// Update run with final inputs/outputs
|
|
@@ -692,10 +695,10 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
692
695
|
if (!childRun.extra.metadata) {
|
|
693
696
|
childRun.extra.metadata = {};
|
|
694
697
|
}
|
|
695
|
-
childRun.extra.metadata
|
|
696
|
-
|
|
697
|
-
ls_agent_type
|
|
698
|
-
}
|
|
698
|
+
const meta = childRun.extra.metadata;
|
|
699
|
+
if (!NON_ROOT_LS_AGENT_TYPES.has(meta.ls_agent_type)) {
|
|
700
|
+
meta.ls_agent_type = "subagent";
|
|
701
|
+
}
|
|
699
702
|
}
|
|
700
703
|
}
|
|
701
704
|
// Track span data type for parent lookups
|