langsmith 0.5.19 → 0.6.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.
- package/dist/client.cjs +460 -22
- package/dist/client.d.ts +165 -1
- package/dist/client.js +464 -26
- package/dist/evaluation/_runner.cjs +4 -7
- package/dist/evaluation/_runner.js +2 -5
- package/dist/evaluation/evaluate_comparative.cjs +10 -10
- package/dist/evaluation/evaluate_comparative.js +1 -1
- package/dist/evaluation/evaluator.cjs +2 -2
- package/dist/evaluation/evaluator.js +1 -1
- package/dist/experimental/anthropic/context.cjs +419 -49
- package/dist/experimental/anthropic/context.js +420 -50
- package/dist/experimental/anthropic/index.cjs +78 -10
- package/dist/experimental/anthropic/index.js +80 -12
- package/dist/experimental/anthropic/messages.cjs +53 -0
- package/dist/experimental/anthropic/messages.d.ts +6 -0
- package/dist/experimental/anthropic/messages.js +52 -0
- package/dist/experimental/anthropic/transcripts.cjs +144 -0
- package/dist/experimental/anthropic/transcripts.d.ts +22 -0
- package/dist/experimental/anthropic/transcripts.js +141 -0
- package/dist/experimental/anthropic/types.d.ts +1 -0
- package/dist/experimental/anthropic/usage.cjs +19 -20
- package/dist/experimental/anthropic/usage.d.ts +2 -1
- package/dist/experimental/anthropic/usage.js +18 -20
- package/dist/experimental/opencode/index.cjs +36 -0
- package/dist/experimental/opencode/index.d.ts +3 -0
- package/dist/experimental/opencode/index.js +32 -0
- package/dist/experimental/opencode/tracer.cjs +389 -0
- package/dist/experimental/opencode/tracer.d.ts +30 -0
- package/dist/experimental/opencode/tracer.js +385 -0
- package/dist/experimental/otel/setup.cjs +1 -1
- package/dist/experimental/otel/setup.js +1 -1
- package/dist/experimental/sandbox/client.cjs +308 -409
- package/dist/experimental/sandbox/client.d.ts +136 -157
- package/dist/experimental/sandbox/client.js +310 -411
- package/dist/experimental/sandbox/errors.cjs +1 -2
- package/dist/experimental/sandbox/errors.d.ts +1 -2
- package/dist/experimental/sandbox/errors.js +1 -2
- package/dist/experimental/sandbox/helpers.cjs +8 -98
- package/dist/experimental/sandbox/helpers.d.ts +0 -29
- package/dist/experimental/sandbox/helpers.js +9 -95
- package/dist/experimental/sandbox/index.cjs +6 -1
- package/dist/experimental/sandbox/index.d.ts +7 -2
- package/dist/experimental/sandbox/index.js +6 -1
- package/dist/experimental/sandbox/sandbox.cjs +71 -13
- package/dist/experimental/sandbox/sandbox.d.ts +39 -9
- package/dist/experimental/sandbox/sandbox.js +71 -13
- package/dist/experimental/sandbox/types.d.ts +147 -137
- package/dist/experimental/vercel/index.cjs +1 -1
- package/dist/experimental/vercel/index.js +1 -1
- package/dist/experimental/vercel/middleware.cjs +2 -1
- package/dist/experimental/vercel/middleware.js +2 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.cjs +8 -7
- package/dist/run_trees.d.ts +7 -0
- package/dist/run_trees.js +7 -6
- package/dist/schemas.d.ts +58 -0
- package/dist/singletons/otel.cjs +3 -2
- package/dist/singletons/otel.js +4 -3
- package/dist/singletons/traceable.cjs +1 -3
- package/dist/singletons/traceable.js +1 -3
- package/dist/traceable.cjs +2 -5
- package/dist/traceable.js +2 -5
- package/dist/utils/_git.cjs +2 -2
- package/dist/utils/_git.js +2 -2
- package/dist/utils/_uuid.cjs +2 -2
- package/dist/utils/_uuid.js +1 -1
- package/dist/utils/env.cjs +35 -2
- package/dist/utils/env.d.ts +9 -0
- package/dist/utils/env.js +34 -2
- package/dist/utils/error.cjs +9 -2
- package/dist/utils/error.d.ts +1 -0
- package/dist/utils/error.js +8 -2
- package/dist/utils/fast-safe-stringify/index.cjs +203 -0
- package/dist/utils/fast-safe-stringify/index.d.ts +46 -0
- package/dist/utils/fast-safe-stringify/index.js +202 -0
- package/dist/utils/jestlike/index.cjs +5 -5
- package/dist/utils/jestlike/index.js +1 -1
- package/dist/utils/jestlike/reporter.cjs +1 -1
- package/dist/utils/jestlike/reporter.js +1 -1
- package/dist/utils/jestlike/vendor/chain.cjs +2 -3
- package/dist/utils/jestlike/vendor/chain.js +2 -3
- package/dist/utils/jestlike/vendor/evaluatedBy.cjs +3 -3
- package/dist/utils/jestlike/vendor/evaluatedBy.js +1 -1
- package/dist/utils/prompts.cjs +7 -2
- package/dist/utils/prompts.d.ts +6 -1
- package/dist/utils/prompts.js +6 -1
- package/dist/utils/serialize_worker.cjs +388 -0
- package/dist/utils/serialize_worker.d.ts +66 -0
- package/dist/utils/serialize_worker.js +382 -0
- package/dist/utils/uuid/src/index.cjs +24 -0
- package/dist/utils/uuid/src/index.d.ts +10 -0
- package/dist/utils/uuid/src/index.js +9 -0
- package/dist/utils/uuid/src/max.cjs +3 -0
- package/dist/utils/uuid/src/max.d.ts +2 -0
- package/dist/utils/uuid/src/max.js +1 -0
- package/dist/utils/uuid/src/nil.cjs +3 -0
- package/dist/utils/uuid/src/nil.d.ts +2 -0
- package/dist/utils/uuid/src/nil.js +1 -0
- package/dist/utils/uuid/src/parse.cjs +23 -0
- package/dist/utils/uuid/src/parse.d.ts +3 -0
- package/dist/utils/uuid/src/parse.js +18 -0
- package/dist/utils/uuid/src/regex.cjs +3 -0
- package/dist/utils/uuid/src/regex.d.ts +2 -0
- package/dist/utils/uuid/src/regex.js +1 -0
- package/dist/utils/uuid/src/rng.cjs +10 -0
- package/dist/utils/uuid/src/rng.d.ts +1 -0
- package/dist/utils/uuid/src/rng.js +7 -0
- package/dist/utils/uuid/src/sha1.cjs +75 -0
- package/dist/utils/uuid/src/sha1.d.ts +2 -0
- package/dist/utils/uuid/src/sha1.js +73 -0
- package/dist/utils/uuid/src/stringify.cjs +55 -0
- package/dist/utils/uuid/src/stringify.d.ts +3 -0
- package/dist/utils/uuid/src/stringify.js +49 -0
- package/dist/utils/uuid/src/types.cjs +2 -0
- package/dist/utils/uuid/src/types.d.ts +22 -0
- package/dist/utils/uuid/src/types.js +1 -0
- package/dist/utils/uuid/src/v35.cjs +52 -0
- package/dist/utils/uuid/src/v35.d.ts +7 -0
- package/dist/utils/uuid/src/v35.js +44 -0
- package/dist/utils/uuid/src/v4.cjs +40 -0
- package/dist/utils/uuid/src/v4.d.ts +4 -0
- package/dist/utils/uuid/src/v4.js +35 -0
- package/dist/utils/uuid/src/v5.cjs +50 -0
- package/dist/utils/uuid/src/v5.d.ts +9 -0
- package/dist/utils/uuid/src/v5.js +9 -0
- package/dist/utils/uuid/src/v7.cjs +88 -0
- package/dist/utils/uuid/src/v7.d.ts +9 -0
- package/dist/utils/uuid/src/v7.js +82 -0
- package/dist/utils/uuid/src/validate.cjs +10 -0
- package/dist/utils/uuid/src/validate.d.ts +2 -0
- package/dist/utils/uuid/src/validate.js +5 -0
- package/dist/utils/uuid/src/version.cjs +13 -0
- package/dist/utils/uuid/src/version.d.ts +2 -0
- package/dist/utils/uuid/src/version.js +8 -0
- package/dist/utils/worker_threads.browser.cjs +16 -0
- package/dist/utils/worker_threads.browser.d.ts +14 -0
- package/dist/utils/worker_threads.browser.js +13 -0
- package/dist/utils/worker_threads.cjs +16 -0
- package/dist/utils/worker_threads.d.ts +13 -0
- package/dist/utils/worker_threads.js +13 -0
- package/dist/uuid.cjs +2 -2
- package/dist/uuid.js +1 -1
- package/dist/vitest/utils/esm.mjs +4 -4
- package/dist/wrappers/gemini.cjs +1 -1
- package/dist/wrappers/gemini.js +1 -1
- package/dist/wrappers/openai.cjs +2 -6
- package/dist/wrappers/openai.js +2 -6
- package/dist/wrappers/openai_agents.cjs +849 -0
- package/dist/wrappers/openai_agents.d.ts +92 -0
- package/dist/wrappers/openai_agents.js +845 -0
- package/experimental/opencode.cjs +1 -0
- package/experimental/opencode.d.cts +1 -0
- package/experimental/opencode.d.ts +1 -0
- package/experimental/opencode.js +1 -0
- package/package.json +47 -25
- package/wrappers/openai_agents.cjs +1 -0
- package/wrappers/openai_agents.d.cts +1 -0
- package/wrappers/openai_agents.d.ts +1 -0
- package/wrappers/openai_agents.js +1 -0
package/dist/client.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import * as uuid from "uuid";
|
|
1
|
+
import * as uuid from "./utils/uuid/src/index.js";
|
|
2
2
|
import { LangSmithToOTELTranslator, } from "./experimental/otel/translator.js";
|
|
3
3
|
import { getDefaultOTLPTracerComponents, getOTELTrace, getOTELContext, } from "./singletons/otel.js";
|
|
4
4
|
import { AsyncCaller } from "./utils/async_caller.js";
|
|
5
5
|
import { convertLangChainMessageToExample, isLangChainMessage, } from "./utils/messages.js";
|
|
6
|
-
import { getEnvironmentVariable, getLangSmithEnvVarsMetadata, getLangSmithEnvironmentVariable, getRuntimeEnvironment,
|
|
6
|
+
import { getEnvironmentVariable, getLangSmithEnvVarsMetadata, getLangSmithEnvironmentVariable, getRuntimeEnvironment, getEnv, resolveTracingMode, } from "./utils/env.js";
|
|
7
7
|
import { __version__ } from "./index.js";
|
|
8
8
|
import { assertUuid } from "./utils/_uuid.js";
|
|
9
9
|
import { warnOnce } from "./utils/warn.js";
|
|
10
|
-
import {
|
|
11
|
-
import { raiseForStatus, isLangSmithNotFoundError } from "./utils/error.js";
|
|
10
|
+
import { parseHubIdentifier } from "./utils/prompts.js";
|
|
11
|
+
import { raiseForStatus, isLangSmithNotFoundError, isLangSmithConflictError, } from "./utils/error.js";
|
|
12
12
|
import { promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
13
13
|
import * as fsUtils from "./utils/fs.js";
|
|
14
14
|
import { _shouldStreamForGlobalFetchImplementation, _getFetchImplementation, } from "./singletons/fetch.js";
|
|
15
|
-
import { serialize as serializePayloadForTracing } from "./utils/fast-safe-stringify/index.js";
|
|
15
|
+
import { serialize as serializePayloadForTracing, estimateSerializedSize, } from "./utils/fast-safe-stringify/index.js";
|
|
16
|
+
import { getSharedSerializeWorker, hasLargeString, } from "./utils/serialize_worker.js";
|
|
17
|
+
function assertPullPublicPromptAllowed(promptIdentifier, dangerouslyPullPublicPrompt) {
|
|
18
|
+
const [owner] = parseHubIdentifier(promptIdentifier);
|
|
19
|
+
if (owner !== "-" && !dangerouslyPullPublicPrompt) {
|
|
20
|
+
throw new Error("Pulling a public prompt by owner/name is disabled by default because prompts may contain untrusted serialized LangChain objects. If you trust this prompt, set `dangerouslyPullPublicPrompt: true` to acknowledge the risk.");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
16
23
|
/**
|
|
17
24
|
* Catches timestamps without a timezone suffix.
|
|
18
25
|
*/
|
|
@@ -152,7 +159,11 @@ export class AutoBatchQueue {
|
|
|
152
159
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise
|
|
153
160
|
itemPromiseResolve = resolve;
|
|
154
161
|
});
|
|
155
|
-
|
|
162
|
+
// Use a cheap structural estimate for soft memory accounting (queue size
|
|
163
|
+
// limit and downstream async caller memory tracking). The exact
|
|
164
|
+
// serialization still happens later, off the hot path, when the batch is
|
|
165
|
+
// assembled for sending.
|
|
166
|
+
const size = estimateSerializedSize(item.item).size;
|
|
156
167
|
// Check if adding this item would exceed the size limit
|
|
157
168
|
// Allow the run if the queue is empty (to support large single traces)
|
|
158
169
|
if (this.sizeBytes + size > this.maxSizeBytes && this.items.length > 0) {
|
|
@@ -215,9 +226,64 @@ export class AutoBatchQueue {
|
|
|
215
226
|
}
|
|
216
227
|
}
|
|
217
228
|
export class Client {
|
|
229
|
+
get tracingMode() {
|
|
230
|
+
return this._tracingMode;
|
|
231
|
+
}
|
|
218
232
|
get _fetch() {
|
|
219
233
|
return this.fetchImplementation || _getFetchImplementation(this.debug);
|
|
220
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Serialize a payload for tracing, optionally offloading the work to a
|
|
237
|
+
* Node worker thread when the runtime supports worker_threads.
|
|
238
|
+
*
|
|
239
|
+
* Falls back to synchronous serialization when:
|
|
240
|
+
* - manualFlushMode is enabled (serverless: worker boot cost > benefit)
|
|
241
|
+
* - worker_threads is unavailable (non-Node runtimes)
|
|
242
|
+
* - the payload contains values that can't be structured-cloned across
|
|
243
|
+
* threads (functions, non-cloneable class instances, streams, etc.)
|
|
244
|
+
* - the worker throws for any other reason
|
|
245
|
+
*
|
|
246
|
+
* In all fallback cases the returned bytes are identical to the sync path.
|
|
247
|
+
*/
|
|
248
|
+
_trackDrain(promise) {
|
|
249
|
+
this._pendingDrains.add(promise);
|
|
250
|
+
promise.finally(() => {
|
|
251
|
+
this._pendingDrains.delete(promise);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
async _serializeBody(payload, errorContext) {
|
|
255
|
+
if (this.manualFlushMode) {
|
|
256
|
+
return serializePayloadForTracing(payload, errorContext);
|
|
257
|
+
}
|
|
258
|
+
// Shape-aware gate: worker offload pays for itself only when the
|
|
259
|
+
// payload is dominated by one or more large strings (V8 can refcount
|
|
260
|
+
// those across isolates instead of copying). For structure-heavy
|
|
261
|
+
// payloads -- many keys, deep nesting, lots of small strings -- the
|
|
262
|
+
// structuredClone walk plus thread-hop cost exceeds the JSON.stringify
|
|
263
|
+
// cost we would pay inline, so we fall through to sync serialize.
|
|
264
|
+
if (!hasLargeString(payload)) {
|
|
265
|
+
return serializePayloadForTracing(payload, errorContext);
|
|
266
|
+
}
|
|
267
|
+
if (this._serializeWorker === undefined) {
|
|
268
|
+
this._serializeWorker = getSharedSerializeWorker();
|
|
269
|
+
}
|
|
270
|
+
if (this._serializeWorker === null) {
|
|
271
|
+
return serializePayloadForTracing(payload, errorContext);
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const bytes = await this._serializeWorker.serialize(payload);
|
|
275
|
+
if (bytes === null) {
|
|
276
|
+
// Worker subsystem unavailable; cache the null to skip re-entry.
|
|
277
|
+
this._serializeWorker = null;
|
|
278
|
+
return serializePayloadForTracing(payload, errorContext);
|
|
279
|
+
}
|
|
280
|
+
return bytes;
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// DataCloneError, worker crash, etc. Fall back silently.
|
|
284
|
+
return serializePayloadForTracing(payload, errorContext);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
221
287
|
constructor(config = {}) {
|
|
222
288
|
Object.defineProperty(this, "apiKey", {
|
|
223
289
|
enumerable: true,
|
|
@@ -279,6 +345,12 @@ export class Client {
|
|
|
279
345
|
writable: true,
|
|
280
346
|
value: void 0
|
|
281
347
|
});
|
|
348
|
+
Object.defineProperty(this, "hideMetadata", {
|
|
349
|
+
enumerable: true,
|
|
350
|
+
configurable: true,
|
|
351
|
+
writable: true,
|
|
352
|
+
value: void 0
|
|
353
|
+
});
|
|
282
354
|
Object.defineProperty(this, "omitTracedRuntimeInfo", {
|
|
283
355
|
enumerable: true,
|
|
284
356
|
configurable: true,
|
|
@@ -376,12 +448,35 @@ export class Client {
|
|
|
376
448
|
writable: true,
|
|
377
449
|
value: false
|
|
378
450
|
});
|
|
451
|
+
Object.defineProperty(this, "_serializeWorker", {
|
|
452
|
+
enumerable: true,
|
|
453
|
+
configurable: true,
|
|
454
|
+
writable: true,
|
|
455
|
+
value: void 0
|
|
456
|
+
});
|
|
457
|
+
/**
|
|
458
|
+
* Tracks in-flight drainAutoBatchQueue promises so awaitPendingTraceBatches
|
|
459
|
+
* can wait on them even if the flush involves async work (worker-thread
|
|
460
|
+
* serialize) that hasn't yet registered with batchIngestCaller.queue.
|
|
461
|
+
*/
|
|
462
|
+
Object.defineProperty(this, "_pendingDrains", {
|
|
463
|
+
enumerable: true,
|
|
464
|
+
configurable: true,
|
|
465
|
+
writable: true,
|
|
466
|
+
value: new Set()
|
|
467
|
+
});
|
|
379
468
|
Object.defineProperty(this, "langSmithToOTELTranslator", {
|
|
380
469
|
enumerable: true,
|
|
381
470
|
configurable: true,
|
|
382
471
|
writable: true,
|
|
383
472
|
value: void 0
|
|
384
473
|
});
|
|
474
|
+
Object.defineProperty(this, "_tracingMode", {
|
|
475
|
+
enumerable: true,
|
|
476
|
+
configurable: true,
|
|
477
|
+
writable: true,
|
|
478
|
+
value: "langsmith"
|
|
479
|
+
});
|
|
385
480
|
Object.defineProperty(this, "fetchImplementation", {
|
|
386
481
|
enumerable: true,
|
|
387
482
|
configurable: true,
|
|
@@ -491,6 +586,7 @@ export class Client {
|
|
|
491
586
|
config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
|
|
492
587
|
this.hideOutputs =
|
|
493
588
|
config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
|
|
589
|
+
this.hideMetadata = config.hideMetadata ?? defaultConfig.hideMetadata;
|
|
494
590
|
this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false;
|
|
495
591
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
496
592
|
this.autoBatchQueue = new AutoBatchQueue(maxMemory);
|
|
@@ -500,7 +596,8 @@ export class Client {
|
|
|
500
596
|
this.batchSizeLimit = config.batchSizeLimit;
|
|
501
597
|
this.fetchOptions = config.fetchOptions || {};
|
|
502
598
|
this.manualFlushMode = config.manualFlushMode ?? this.manualFlushMode;
|
|
503
|
-
|
|
599
|
+
this._tracingMode = resolveTracingMode(config.tracingMode);
|
|
600
|
+
if (this._tracingMode === "otel") {
|
|
504
601
|
this.langSmithToOTELTranslator = new LangSmithToOTELTranslator();
|
|
505
602
|
}
|
|
506
603
|
// Cache metadata env vars once during construction to avoid repeatedly scanning process.env
|
|
@@ -540,12 +637,14 @@ export class Client {
|
|
|
540
637
|
const apiUrl = getLangSmithEnvironmentVariable("ENDPOINT") ?? DEFAULT_API_URL;
|
|
541
638
|
const hideInputs = getLangSmithEnvironmentVariable("HIDE_INPUTS") === "true";
|
|
542
639
|
const hideOutputs = getLangSmithEnvironmentVariable("HIDE_OUTPUTS") === "true";
|
|
640
|
+
const hideMetadata = getLangSmithEnvironmentVariable("HIDE_METADATA") === "true";
|
|
543
641
|
return {
|
|
544
642
|
apiUrl: apiUrl,
|
|
545
643
|
apiKey: apiKey,
|
|
546
644
|
webUrl: undefined,
|
|
547
645
|
hideInputs: hideInputs,
|
|
548
646
|
hideOutputs: hideOutputs,
|
|
647
|
+
hideMetadata: hideMetadata,
|
|
549
648
|
};
|
|
550
649
|
}
|
|
551
650
|
getHostUrl() {
|
|
@@ -577,6 +676,10 @@ export class Client {
|
|
|
577
676
|
this.webUrl = "https://aws.smith.langchain.com";
|
|
578
677
|
return this.webUrl;
|
|
579
678
|
}
|
|
679
|
+
else if (this.apiUrl.split(".", 1)[0].includes("apac")) {
|
|
680
|
+
this.webUrl = "https://apac.smith.langchain.com";
|
|
681
|
+
return this.webUrl;
|
|
682
|
+
}
|
|
580
683
|
else if (this.apiUrl.split(".", 1)[0].includes("beta")) {
|
|
581
684
|
this.webUrl = "https://beta.smith.langchain.com";
|
|
582
685
|
return this.webUrl;
|
|
@@ -641,6 +744,18 @@ export class Client {
|
|
|
641
744
|
}
|
|
642
745
|
return outputs;
|
|
643
746
|
}
|
|
747
|
+
async processMetadata(metadata) {
|
|
748
|
+
if (this.hideMetadata === false) {
|
|
749
|
+
return metadata;
|
|
750
|
+
}
|
|
751
|
+
if (this.hideMetadata === true) {
|
|
752
|
+
return {};
|
|
753
|
+
}
|
|
754
|
+
if (typeof this.hideMetadata === "function") {
|
|
755
|
+
return this.hideMetadata(metadata);
|
|
756
|
+
}
|
|
757
|
+
return metadata;
|
|
758
|
+
}
|
|
644
759
|
/**
|
|
645
760
|
* Filter content from new_token events to prevent streaming LLM output
|
|
646
761
|
* from being uploaded via events.
|
|
@@ -667,6 +782,12 @@ export class Client {
|
|
|
667
782
|
if (runParams.outputs !== undefined) {
|
|
668
783
|
runParams.outputs = await this.processOutputs(runParams.outputs);
|
|
669
784
|
}
|
|
785
|
+
if (runParams.extra != null && "metadata" in runParams.extra) {
|
|
786
|
+
runParams.extra = {
|
|
787
|
+
...runParams.extra,
|
|
788
|
+
metadata: await this.processMetadata(runParams.extra.metadata),
|
|
789
|
+
};
|
|
790
|
+
}
|
|
670
791
|
if (runParams.events !== undefined) {
|
|
671
792
|
runParams.events = this._filterNewTokenEvents(runParams.events);
|
|
672
793
|
}
|
|
@@ -1019,18 +1140,18 @@ export class Client {
|
|
|
1019
1140
|
const sizeLimit = await this._getBatchSizeLimit();
|
|
1020
1141
|
if (this.autoBatchQueue.sizeBytes > sizeLimitBytes ||
|
|
1021
1142
|
this.autoBatchQueue.items.length > sizeLimit) {
|
|
1022
|
-
|
|
1143
|
+
this._trackDrain(this.drainAutoBatchQueue({
|
|
1023
1144
|
batchSizeLimitBytes: sizeLimitBytes,
|
|
1024
1145
|
batchSizeLimit: sizeLimit,
|
|
1025
|
-
});
|
|
1146
|
+
}));
|
|
1026
1147
|
}
|
|
1027
1148
|
if (this.autoBatchQueue.items.length > 0) {
|
|
1028
1149
|
this.autoBatchTimeout = setTimeout(() => {
|
|
1029
1150
|
this.autoBatchTimeout = undefined;
|
|
1030
|
-
|
|
1151
|
+
this._trackDrain(this.drainAutoBatchQueue({
|
|
1031
1152
|
batchSizeLimitBytes: sizeLimitBytes,
|
|
1032
1153
|
batchSizeLimit: sizeLimit,
|
|
1033
|
-
});
|
|
1154
|
+
}));
|
|
1034
1155
|
}, this.autoBatchAggregationDelayMs);
|
|
1035
1156
|
}
|
|
1036
1157
|
return itemPromise;
|
|
@@ -1039,7 +1160,7 @@ export class Client {
|
|
|
1039
1160
|
const response = await this.caller.call(async () => {
|
|
1040
1161
|
const res = await this._fetch(`${this.apiUrl}/info`, {
|
|
1041
1162
|
method: "GET",
|
|
1042
|
-
headers: { Accept: "application/json" },
|
|
1163
|
+
headers: { ...this._mergedHeaders, Accept: "application/json" },
|
|
1043
1164
|
signal: AbortSignal.timeout(SERVER_INFO_REQUEST_TIMEOUT_MS),
|
|
1044
1165
|
...this.fetchOptions,
|
|
1045
1166
|
});
|
|
@@ -1210,7 +1331,7 @@ export class Client {
|
|
|
1210
1331
|
.map((item) => item.id)
|
|
1211
1332
|
.concat(batchChunks.patch.map((item) => item.id))
|
|
1212
1333
|
.join(",");
|
|
1213
|
-
await this._postBatchIngestRuns(
|
|
1334
|
+
await this._postBatchIngestRuns(await this._serializeBody(batchChunks, `Ingesting runs with ids: ${runIds}`), options);
|
|
1214
1335
|
}
|
|
1215
1336
|
}
|
|
1216
1337
|
async _postBatchIngestRuns(body, options) {
|
|
@@ -1311,7 +1432,7 @@ export class Client {
|
|
|
1311
1432
|
const { inputs, outputs, events, extra, error, serialized, attachments, ...payload } = originalPayload;
|
|
1312
1433
|
const fields = { inputs, outputs, events, extra, error, serialized };
|
|
1313
1434
|
// encode the main run payload
|
|
1314
|
-
const stringifiedPayload =
|
|
1435
|
+
const stringifiedPayload = await this._serializeBody(payload, `Serializing for multipart ingestion of run with id: ${payload.id}`);
|
|
1315
1436
|
accumulatedParts.push({
|
|
1316
1437
|
name: `${method}.${payload.id}`,
|
|
1317
1438
|
payload: new Blob([stringifiedPayload], {
|
|
@@ -1323,7 +1444,7 @@ export class Client {
|
|
|
1323
1444
|
if (value === undefined) {
|
|
1324
1445
|
continue;
|
|
1325
1446
|
}
|
|
1326
|
-
const stringifiedValue =
|
|
1447
|
+
const stringifiedValue = await this._serializeBody(value, `Serializing ${key} for multipart ingestion of run with id: ${payload.id}`);
|
|
1327
1448
|
accumulatedParts.push({
|
|
1328
1449
|
name: `${method}.${payload.id}.${key}`,
|
|
1329
1450
|
payload: new Blob([stringifiedValue], {
|
|
@@ -1514,6 +1635,12 @@ export class Client {
|
|
|
1514
1635
|
if (run.outputs) {
|
|
1515
1636
|
run.outputs = await this.processOutputs(run.outputs);
|
|
1516
1637
|
}
|
|
1638
|
+
if (run.extra != null && "metadata" in run.extra) {
|
|
1639
|
+
run.extra = {
|
|
1640
|
+
...run.extra,
|
|
1641
|
+
metadata: await this.processMetadata(run.extra.metadata),
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1517
1644
|
if (run.events) {
|
|
1518
1645
|
run.events = this._filterNewTokenEvents(run.events);
|
|
1519
1646
|
}
|
|
@@ -2329,7 +2456,7 @@ export class Client {
|
|
|
2329
2456
|
// projectId querying
|
|
2330
2457
|
return true;
|
|
2331
2458
|
}
|
|
2332
|
-
catch (
|
|
2459
|
+
catch (_e) {
|
|
2333
2460
|
return false;
|
|
2334
2461
|
}
|
|
2335
2462
|
}
|
|
@@ -3750,7 +3877,7 @@ export class Client {
|
|
|
3750
3877
|
return json.commits[0].commit_hash;
|
|
3751
3878
|
}
|
|
3752
3879
|
async _likeOrUnlikePrompt(promptIdentifier, like) {
|
|
3753
|
-
const [owner, promptName, _] =
|
|
3880
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
3754
3881
|
const body = JSON.stringify({ like: like });
|
|
3755
3882
|
const response = await this.caller.call(async () => {
|
|
3756
3883
|
const res = await this._fetch(`${this.apiUrl}/likes/${owner}/${promptName}`, {
|
|
@@ -3769,7 +3896,7 @@ export class Client {
|
|
|
3769
3896
|
return response.json();
|
|
3770
3897
|
}
|
|
3771
3898
|
async _getPromptUrl(promptIdentifier) {
|
|
3772
|
-
const [owner, promptName, commitHash] =
|
|
3899
|
+
const [owner, promptName, commitHash] = parseHubIdentifier(promptIdentifier);
|
|
3773
3900
|
if (!(await this._currentTenantIsOwner(owner))) {
|
|
3774
3901
|
if (commitHash !== "latest") {
|
|
3775
3902
|
return `${this.getHostUrl()}/hub/${owner}/${promptName}/${commitHash.substring(0, 8)}`;
|
|
@@ -3861,7 +3988,7 @@ export class Client {
|
|
|
3861
3988
|
* ```
|
|
3862
3989
|
*/
|
|
3863
3990
|
async *listCommits(promptIdentifier) {
|
|
3864
|
-
const [owner, promptName, _] =
|
|
3991
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
3865
3992
|
for await (const commits of this._getPaginated(`/commits/${owner}/${promptName}/`, new URLSearchParams(), (res) => res.commits)) {
|
|
3866
3993
|
yield* commits;
|
|
3867
3994
|
}
|
|
@@ -3924,7 +4051,7 @@ export class Client {
|
|
|
3924
4051
|
* ```
|
|
3925
4052
|
*/
|
|
3926
4053
|
async getPrompt(promptIdentifier) {
|
|
3927
|
-
const [owner, promptName, _] =
|
|
4054
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
3928
4055
|
const response = await this.caller.call(async () => {
|
|
3929
4056
|
const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${promptName}`, {
|
|
3930
4057
|
method: "GET",
|
|
@@ -3981,7 +4108,7 @@ export class Client {
|
|
|
3981
4108
|
You can add a handle by creating a public prompt at:\n
|
|
3982
4109
|
https://smith.langchain.com/prompts`);
|
|
3983
4110
|
}
|
|
3984
|
-
const [owner, promptName, _] =
|
|
4111
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
3985
4112
|
if (!(await this._currentTenantIsOwner(owner))) {
|
|
3986
4113
|
throw await this._ownerConflictError("create a prompt", owner);
|
|
3987
4114
|
}
|
|
@@ -4040,7 +4167,7 @@ export class Client {
|
|
|
4040
4167
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
4041
4168
|
throw new Error("Prompt does not exist, you must create it first.");
|
|
4042
4169
|
}
|
|
4043
|
-
const [owner, promptName, _] =
|
|
4170
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
4044
4171
|
const resolvedParentCommitHash = options?.parentCommitHash === "latest" || !options?.parentCommitHash
|
|
4045
4172
|
? await this._getLatestCommitHash(`${owner}/${promptName}`)
|
|
4046
4173
|
: options?.parentCommitHash;
|
|
@@ -4238,7 +4365,7 @@ export class Client {
|
|
|
4238
4365
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
4239
4366
|
throw new Error("Prompt does not exist, you must create it first.");
|
|
4240
4367
|
}
|
|
4241
|
-
const [owner, promptName] =
|
|
4368
|
+
const [owner, promptName] = parseHubIdentifier(promptIdentifier);
|
|
4242
4369
|
if (!(await this._currentTenantIsOwner(owner))) {
|
|
4243
4370
|
throw await this._ownerConflictError("update a prompt", owner);
|
|
4244
4371
|
}
|
|
@@ -4278,7 +4405,7 @@ export class Client {
|
|
|
4278
4405
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
4279
4406
|
throw new Error("Prompt does not exist, you must create it first.");
|
|
4280
4407
|
}
|
|
4281
|
-
const [owner, promptName, _] =
|
|
4408
|
+
const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
|
|
4282
4409
|
if (!(await this._currentTenantIsOwner(owner))) {
|
|
4283
4410
|
throw await this._ownerConflictError("delete a prompt", owner);
|
|
4284
4411
|
}
|
|
@@ -4306,7 +4433,7 @@ export class Client {
|
|
|
4306
4433
|
* Fetch a prompt commit directly from the API (bypassing cache).
|
|
4307
4434
|
*/
|
|
4308
4435
|
async _fetchPromptFromApi(promptIdentifier, options) {
|
|
4309
|
-
const [owner, promptName, commitHash] =
|
|
4436
|
+
const [owner, promptName, commitHash] = parseHubIdentifier(promptIdentifier);
|
|
4310
4437
|
const response = await this.caller.call(async () => {
|
|
4311
4438
|
const res = await this._fetch(`${this.apiUrl}/commits/${owner}/${promptName}/${commitHash}${options?.includeModel ? "?include_model=true" : ""}`, {
|
|
4312
4439
|
method: "GET",
|
|
@@ -4324,9 +4451,28 @@ export class Client {
|
|
|
4324
4451
|
commit_hash: result.commit_hash,
|
|
4325
4452
|
manifest: result.manifest,
|
|
4326
4453
|
examples: result.examples,
|
|
4454
|
+
hub_model_config: result.model_config,
|
|
4455
|
+
hub_model_provider: result.model_provider,
|
|
4327
4456
|
};
|
|
4328
4457
|
}
|
|
4458
|
+
/**
|
|
4459
|
+
* Pull a prompt commit from the LangSmith API.
|
|
4460
|
+
*
|
|
4461
|
+
* Public prompts referenced by owner/name cross a trust boundary because the
|
|
4462
|
+
* prompt manifest may contain serialized LangChain objects and configuration
|
|
4463
|
+
* that affect runtime behavior. For example, a prompt can intentionally
|
|
4464
|
+
* configure a model with a custom base URL, headers, model name, or other
|
|
4465
|
+
* constructor arguments. These are supported features, but they also mean the
|
|
4466
|
+
* prompt contents should be treated as executable configuration rather than
|
|
4467
|
+
* plain text.
|
|
4468
|
+
*
|
|
4469
|
+
* Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
|
|
4470
|
+
* the prompt contents, not merely the publishing account. Prompts from your
|
|
4471
|
+
* own or your organization's account can still be unsafe if that account or
|
|
4472
|
+
* prompt was compromised.
|
|
4473
|
+
*/
|
|
4329
4474
|
async pullPromptCommit(promptIdentifier, options) {
|
|
4475
|
+
assertPullPublicPromptAllowed(promptIdentifier, options?.dangerouslyPullPublicPrompt);
|
|
4330
4476
|
// Check cache first if not skipped
|
|
4331
4477
|
const refreshFunc = this._fetchPromptFromApi.bind(this, promptIdentifier, options);
|
|
4332
4478
|
if (!options?.skipCache && this._promptCache) {
|
|
@@ -4346,12 +4492,26 @@ export class Client {
|
|
|
4346
4492
|
/**
|
|
4347
4493
|
* This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
|
|
4348
4494
|
* Using this method directly returns the JSON string of the prompt rather than a LangChain object.
|
|
4495
|
+
*
|
|
4496
|
+
* Public prompts referenced by owner/name cross a trust boundary because the
|
|
4497
|
+
* prompt manifest may contain serialized LangChain objects and configuration
|
|
4498
|
+
* that affect runtime behavior. For example, a prompt can intentionally
|
|
4499
|
+
* configure a model with a custom base URL, headers, model name, or other
|
|
4500
|
+
* constructor arguments. These are supported features, but they also mean the
|
|
4501
|
+
* prompt contents should be treated as executable configuration rather than
|
|
4502
|
+
* plain text.
|
|
4503
|
+
*
|
|
4504
|
+
* Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
|
|
4505
|
+
* the prompt contents, not merely the publishing account. Prompts from your
|
|
4506
|
+
* own or your organization's account can still be unsafe if that account or
|
|
4507
|
+
* prompt was compromised.
|
|
4349
4508
|
* @private
|
|
4350
4509
|
*/
|
|
4351
4510
|
async _pullPrompt(promptIdentifier, options) {
|
|
4352
4511
|
const promptObject = await this.pullPromptCommit(promptIdentifier, {
|
|
4353
4512
|
includeModel: options?.includeModel,
|
|
4354
4513
|
skipCache: options?.skipCache,
|
|
4514
|
+
dangerouslyPullPublicPrompt: options?.dangerouslyPullPublicPrompt,
|
|
4355
4515
|
});
|
|
4356
4516
|
const prompt = JSON.stringify(promptObject.manifest);
|
|
4357
4517
|
return prompt;
|
|
@@ -4386,6 +4546,251 @@ export class Client {
|
|
|
4386
4546
|
});
|
|
4387
4547
|
return url;
|
|
4388
4548
|
}
|
|
4549
|
+
/**
|
|
4550
|
+
* Check if an agent repo exists.
|
|
4551
|
+
*/
|
|
4552
|
+
async agentExists(identifier) {
|
|
4553
|
+
const [owner, name] = parseHubIdentifier(identifier);
|
|
4554
|
+
return this._repoExists(owner, name);
|
|
4555
|
+
}
|
|
4556
|
+
/**
|
|
4557
|
+
* Check if a skill repo exists.
|
|
4558
|
+
*/
|
|
4559
|
+
async skillExists(identifier) {
|
|
4560
|
+
const [owner, name] = parseHubIdentifier(identifier);
|
|
4561
|
+
return this._repoExists(owner, name);
|
|
4562
|
+
}
|
|
4563
|
+
/**
|
|
4564
|
+
* Pull an agent directory from Hub.
|
|
4565
|
+
* @param identifier The identifier (owner/name[:version]).
|
|
4566
|
+
* @param options.version Commit hash or tag; overrides identifier's version.
|
|
4567
|
+
*/
|
|
4568
|
+
async pullAgent(identifier, options) {
|
|
4569
|
+
return (await this._pullDirectory(identifier, "agent", options?.version));
|
|
4570
|
+
}
|
|
4571
|
+
/**
|
|
4572
|
+
* Pull a skill directory from Hub.
|
|
4573
|
+
*/
|
|
4574
|
+
async pullSkill(identifier, options) {
|
|
4575
|
+
return (await this._pullDirectory(identifier, "skill", options?.version));
|
|
4576
|
+
}
|
|
4577
|
+
/**
|
|
4578
|
+
* Push an agent to Hub. Creates the repo if missing, patches metadata if
|
|
4579
|
+
* provided, then commits the given files.
|
|
4580
|
+
* @returns The URL of the resulting commit.
|
|
4581
|
+
*/
|
|
4582
|
+
async pushAgent(identifier, options) {
|
|
4583
|
+
return this._pushDirectory(identifier, "agent", options);
|
|
4584
|
+
}
|
|
4585
|
+
/**
|
|
4586
|
+
* Push a skill to Hub.
|
|
4587
|
+
*/
|
|
4588
|
+
async pushSkill(identifier, options) {
|
|
4589
|
+
return this._pushDirectory(identifier, "skill", options);
|
|
4590
|
+
}
|
|
4591
|
+
/**
|
|
4592
|
+
* Delete an agent and all its owned child file repos.
|
|
4593
|
+
*/
|
|
4594
|
+
async deleteAgent(identifier) {
|
|
4595
|
+
return this._deleteDirectory(identifier);
|
|
4596
|
+
}
|
|
4597
|
+
/**
|
|
4598
|
+
* Delete a skill and all its owned child file repos.
|
|
4599
|
+
*/
|
|
4600
|
+
async deleteSkill(identifier) {
|
|
4601
|
+
return this._deleteDirectory(identifier);
|
|
4602
|
+
}
|
|
4603
|
+
/**
|
|
4604
|
+
* List agent repos. Yields one at a time, auto-paginating.
|
|
4605
|
+
*/
|
|
4606
|
+
async *listAgents(options) {
|
|
4607
|
+
yield* this._listReposByType("agent", options);
|
|
4608
|
+
}
|
|
4609
|
+
/**
|
|
4610
|
+
* List skill repos. Yields one at a time, auto-paginating.
|
|
4611
|
+
*/
|
|
4612
|
+
async *listSkills(options) {
|
|
4613
|
+
yield* this._listReposByType("skill", options);
|
|
4614
|
+
}
|
|
4615
|
+
async *_listReposByType(repoType, options) {
|
|
4616
|
+
const params = new URLSearchParams();
|
|
4617
|
+
params.append("repo_type", repoType);
|
|
4618
|
+
params.append("is_archived", (!!options?.isArchived).toString());
|
|
4619
|
+
if (options?.isPublic !== undefined) {
|
|
4620
|
+
params.append("is_public", options.isPublic.toString());
|
|
4621
|
+
}
|
|
4622
|
+
if (options?.query) {
|
|
4623
|
+
params.append("query", options.query);
|
|
4624
|
+
}
|
|
4625
|
+
for await (const repos of this._getPaginated("/repos", params, (res) => res.repos)) {
|
|
4626
|
+
yield* repos;
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
async _pullDirectory(identifier, repoType, version) {
|
|
4630
|
+
const [owner, name, parsedVersion] = parseHubIdentifier(identifier);
|
|
4631
|
+
const resolvedVersion = version ?? (parsedVersion !== "latest" ? parsedVersion : undefined);
|
|
4632
|
+
const url = new URL(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`);
|
|
4633
|
+
url.searchParams.set("repo_type", repoType);
|
|
4634
|
+
if (resolvedVersion) {
|
|
4635
|
+
url.searchParams.set("commit", resolvedVersion);
|
|
4636
|
+
}
|
|
4637
|
+
const response = await this.caller.call(async () => {
|
|
4638
|
+
const res = await this._fetch(url.toString(), {
|
|
4639
|
+
method: "GET",
|
|
4640
|
+
headers: this._mergedHeaders,
|
|
4641
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4642
|
+
...this.fetchOptions,
|
|
4643
|
+
});
|
|
4644
|
+
await raiseForStatus(res, "pull directory");
|
|
4645
|
+
return res;
|
|
4646
|
+
});
|
|
4647
|
+
return (await response.json());
|
|
4648
|
+
}
|
|
4649
|
+
async _pushDirectory(identifier, repoType, options) {
|
|
4650
|
+
if (options.parentCommit !== undefined &&
|
|
4651
|
+
(options.parentCommit.length < 8 || options.parentCommit.length > 64)) {
|
|
4652
|
+
throw new Error("parent_commit must be 8-64 characters");
|
|
4653
|
+
}
|
|
4654
|
+
const [owner, name] = parseHubIdentifier(identifier);
|
|
4655
|
+
if (!(await this._currentTenantIsOwner(owner))) {
|
|
4656
|
+
throw await this._ownerConflictError(`push ${repoType}`, owner);
|
|
4657
|
+
}
|
|
4658
|
+
if (await this._repoExists(owner, name)) {
|
|
4659
|
+
if (options.description !== undefined ||
|
|
4660
|
+
options.readme !== undefined ||
|
|
4661
|
+
options.tags !== undefined ||
|
|
4662
|
+
options.isPublic !== undefined) {
|
|
4663
|
+
await this._updateRepoMetadata(owner, name, options);
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
else {
|
|
4667
|
+
const REPO_HANDLE_PATTERN = /^[a-z][a-z0-9-_]*$/;
|
|
4668
|
+
if (!REPO_HANDLE_PATTERN.test(name)) {
|
|
4669
|
+
throw new Error(`Invalid repo_handle ${JSON.stringify(name)}: must match ${REPO_HANDLE_PATTERN}`);
|
|
4670
|
+
}
|
|
4671
|
+
await this._createRepo(name, repoType, options);
|
|
4672
|
+
}
|
|
4673
|
+
const body = { files: options.files };
|
|
4674
|
+
if (options.parentCommit) {
|
|
4675
|
+
body.parent_commit = options.parentCommit;
|
|
4676
|
+
}
|
|
4677
|
+
const response = await this.caller.call(async () => {
|
|
4678
|
+
const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories/commits`, {
|
|
4679
|
+
method: "POST",
|
|
4680
|
+
headers: {
|
|
4681
|
+
...this._mergedHeaders,
|
|
4682
|
+
"Content-Type": "application/json",
|
|
4683
|
+
},
|
|
4684
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4685
|
+
...this.fetchOptions,
|
|
4686
|
+
body: JSON.stringify(body),
|
|
4687
|
+
});
|
|
4688
|
+
await raiseForStatus(res, `push ${repoType}`);
|
|
4689
|
+
return res;
|
|
4690
|
+
});
|
|
4691
|
+
const data = (await response.json());
|
|
4692
|
+
const commitHash = data.commit.commit_hash;
|
|
4693
|
+
return `${this.getHostUrl()}/hub/${owner}/${name}:${commitHash.slice(0, 8)}`;
|
|
4694
|
+
}
|
|
4695
|
+
async _deleteDirectory(identifier) {
|
|
4696
|
+
const [owner, name] = parseHubIdentifier(identifier);
|
|
4697
|
+
if (!(await this._currentTenantIsOwner(owner))) {
|
|
4698
|
+
throw await this._ownerConflictError("delete", owner);
|
|
4699
|
+
}
|
|
4700
|
+
await this.caller.call(async () => {
|
|
4701
|
+
const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`, {
|
|
4702
|
+
method: "DELETE",
|
|
4703
|
+
headers: this._mergedHeaders,
|
|
4704
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4705
|
+
...this.fetchOptions,
|
|
4706
|
+
});
|
|
4707
|
+
await raiseForStatus(res, "delete directory");
|
|
4708
|
+
return res;
|
|
4709
|
+
});
|
|
4710
|
+
}
|
|
4711
|
+
async _repoExists(owner, name) {
|
|
4712
|
+
try {
|
|
4713
|
+
await this.caller.call(async () => {
|
|
4714
|
+
const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${name}`, {
|
|
4715
|
+
method: "GET",
|
|
4716
|
+
headers: this._mergedHeaders,
|
|
4717
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4718
|
+
...this.fetchOptions,
|
|
4719
|
+
});
|
|
4720
|
+
await raiseForStatus(res, "check repo exists");
|
|
4721
|
+
return res;
|
|
4722
|
+
});
|
|
4723
|
+
return true;
|
|
4724
|
+
}
|
|
4725
|
+
catch (e) {
|
|
4726
|
+
if (isLangSmithNotFoundError(e)) {
|
|
4727
|
+
return false;
|
|
4728
|
+
}
|
|
4729
|
+
throw e;
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
async _createRepo(name, repoType, options) {
|
|
4733
|
+
const body = {
|
|
4734
|
+
repo_handle: name,
|
|
4735
|
+
repo_type: repoType,
|
|
4736
|
+
is_public: !!options.isPublic,
|
|
4737
|
+
};
|
|
4738
|
+
if (options.description !== undefined)
|
|
4739
|
+
body.description = options.description;
|
|
4740
|
+
if (options.readme !== undefined)
|
|
4741
|
+
body.readme = options.readme;
|
|
4742
|
+
if (options.tags !== undefined)
|
|
4743
|
+
body.tags = options.tags;
|
|
4744
|
+
try {
|
|
4745
|
+
await this.caller.call(async () => {
|
|
4746
|
+
const res = await this._fetch(`${this.apiUrl}/repos/`, {
|
|
4747
|
+
method: "POST",
|
|
4748
|
+
headers: {
|
|
4749
|
+
...this._mergedHeaders,
|
|
4750
|
+
"Content-Type": "application/json",
|
|
4751
|
+
},
|
|
4752
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4753
|
+
...this.fetchOptions,
|
|
4754
|
+
body: JSON.stringify(body),
|
|
4755
|
+
});
|
|
4756
|
+
await raiseForStatus(res, `create ${repoType}`);
|
|
4757
|
+
return res;
|
|
4758
|
+
});
|
|
4759
|
+
}
|
|
4760
|
+
catch (e) {
|
|
4761
|
+
if (isLangSmithConflictError(e)) {
|
|
4762
|
+
return;
|
|
4763
|
+
}
|
|
4764
|
+
throw e;
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
async _updateRepoMetadata(owner, name, options) {
|
|
4768
|
+
const body = {};
|
|
4769
|
+
if (options.description !== undefined)
|
|
4770
|
+
body.description = options.description;
|
|
4771
|
+
if (options.readme !== undefined)
|
|
4772
|
+
body.readme = options.readme;
|
|
4773
|
+
if (options.tags !== undefined)
|
|
4774
|
+
body.tags = options.tags;
|
|
4775
|
+
if (options.isPublic !== undefined)
|
|
4776
|
+
body.is_public = options.isPublic;
|
|
4777
|
+
if (Object.keys(body).length === 0)
|
|
4778
|
+
return;
|
|
4779
|
+
await this.caller.call(async () => {
|
|
4780
|
+
const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${name}`, {
|
|
4781
|
+
method: "PATCH",
|
|
4782
|
+
headers: {
|
|
4783
|
+
...this._mergedHeaders,
|
|
4784
|
+
"Content-Type": "application/json",
|
|
4785
|
+
},
|
|
4786
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
4787
|
+
...this.fetchOptions,
|
|
4788
|
+
body: JSON.stringify(body),
|
|
4789
|
+
});
|
|
4790
|
+
await raiseForStatus(res, "update repo metadata");
|
|
4791
|
+
return res;
|
|
4792
|
+
});
|
|
4793
|
+
}
|
|
4389
4794
|
/**
|
|
4390
4795
|
* Clone a public dataset to your own langsmith tenant.
|
|
4391
4796
|
* This operation is idempotent. If you already have a dataset with the given name,
|
|
@@ -4463,7 +4868,7 @@ export class Client {
|
|
|
4463
4868
|
throw new Error(`Invalid public ${kind} URL: ${urlOrToken}`);
|
|
4464
4869
|
}
|
|
4465
4870
|
}
|
|
4466
|
-
catch (
|
|
4871
|
+
catch (_error) {
|
|
4467
4872
|
throw new Error(`Invalid public ${kind} URL or token: ${urlOrToken}`);
|
|
4468
4873
|
}
|
|
4469
4874
|
}
|
|
@@ -4517,6 +4922,12 @@ export class Client {
|
|
|
4517
4922
|
* ```
|
|
4518
4923
|
*/
|
|
4519
4924
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
4925
|
+
// Wait for any in-flight drains (whose serialize work may still be
|
|
4926
|
+
// in-progress on a worker thread and not yet registered with the
|
|
4927
|
+
// batchIngestCaller queue) before checking queue idleness.
|
|
4928
|
+
while (this._pendingDrains.size > 0) {
|
|
4929
|
+
await Promise.all([...this._pendingDrains]);
|
|
4930
|
+
}
|
|
4520
4931
|
await Promise.all([
|
|
4521
4932
|
...this.autoBatchQueue.items.map(({ itemPromise }) => itemPromise),
|
|
4522
4933
|
this.batchIngestCaller.queue.onIdle(),
|
|
@@ -4525,6 +4936,33 @@ export class Client {
|
|
|
4525
4936
|
await getDefaultOTLPTracerComponents()?.DEFAULT_LANGSMITH_SPAN_PROCESSOR?.forceFlush();
|
|
4526
4937
|
}
|
|
4527
4938
|
}
|
|
4939
|
+
/**
|
|
4940
|
+
* Returns a string representation of the Client instance.
|
|
4941
|
+
* This method is called when the object is converted to a string
|
|
4942
|
+
* or logged, ensuring sensitive information like API keys is not exposed.
|
|
4943
|
+
*
|
|
4944
|
+
* @returns A string representation of the Client.
|
|
4945
|
+
*/
|
|
4946
|
+
toString() {
|
|
4947
|
+
const params = [`apiUrl=${JSON.stringify(this.apiUrl)}`];
|
|
4948
|
+
if (this.webUrl !== undefined) {
|
|
4949
|
+
params.push(`webUrl=${JSON.stringify(this.webUrl)}`);
|
|
4950
|
+
}
|
|
4951
|
+
if (this.workspaceId !== undefined) {
|
|
4952
|
+
params.push(`workspaceId=${JSON.stringify(this.workspaceId)}`);
|
|
4953
|
+
}
|
|
4954
|
+
return `[LangSmithClient ${params.join(" ")}]`;
|
|
4955
|
+
}
|
|
4956
|
+
/**
|
|
4957
|
+
* Custom inspect method for Node.js.
|
|
4958
|
+
* This method is called when the object is inspected in the Node.js REPL
|
|
4959
|
+
* or with console.log, ensuring sensitive information like API keys is not exposed.
|
|
4960
|
+
*
|
|
4961
|
+
* @returns A string representation of the Client for inspection.
|
|
4962
|
+
*/
|
|
4963
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
4964
|
+
return this.toString();
|
|
4965
|
+
}
|
|
4528
4966
|
}
|
|
4529
4967
|
Object.defineProperty(Client, "_fallbackDirsCreated", {
|
|
4530
4968
|
enumerable: true,
|