langsmith 0.5.6 → 0.5.8
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 +378 -3
- package/dist/client.d.ts +202 -2
- package/dist/client.js +378 -3
- package/dist/evaluation/evaluator.cjs +1 -1
- package/dist/evaluation/evaluator.js +2 -2
- package/dist/experimental/anthropic/index.cjs +15 -1
- package/dist/experimental/anthropic/index.js +15 -1
- package/dist/experimental/vercel/index.cjs +23 -5
- package/dist/experimental/vercel/index.js +23 -5
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/error.cjs +16 -0
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.js +15 -0
- package/dist/utils/fs.browser.cjs +51 -0
- package/dist/utils/fs.browser.d.ts +25 -0
- package/dist/utils/fs.browser.js +37 -0
- package/dist/utils/fs.cjs +101 -0
- package/dist/utils/fs.d.ts +21 -0
- package/dist/utils/fs.js +54 -0
- package/dist/utils/jestlike/vendor/evaluatedBy.cjs +2 -2
- package/dist/utils/jestlike/vendor/evaluatedBy.js +3 -3
- package/dist/utils/prompt_cache/index.cjs +31 -5
- package/dist/utils/prompt_cache/index.d.ts +3 -2
- package/dist/utils/prompt_cache/index.js +31 -5
- package/dist/utils/prompts.cjs +4 -3
- package/dist/utils/prompts.js +4 -3
- package/dist/wrappers/anthropic.cjs +8 -3
- package/dist/wrappers/anthropic.d.ts +5 -0
- package/dist/wrappers/anthropic.js +8 -4
- package/package.json +4 -4
- package/dist/utils/prompt_cache/fs.browser.cjs +0 -24
- package/dist/utils/prompt_cache/fs.browser.d.ts +0 -16
- package/dist/utils/prompt_cache/fs.browser.js +0 -20
- package/dist/utils/prompt_cache/fs.cjs +0 -86
- package/dist/utils/prompt_cache/fs.d.ts +0 -16
- package/dist/utils/prompt_cache/fs.js +0 -49
package/dist/client.js
CHANGED
|
@@ -10,6 +10,7 @@ import { warnOnce } from "./utils/warn.js";
|
|
|
10
10
|
import { parsePromptIdentifier } from "./utils/prompts.js";
|
|
11
11
|
import { raiseForStatus, isLangSmithNotFoundError } from "./utils/error.js";
|
|
12
12
|
import { promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
13
|
+
import * as fsUtils from "./utils/fs.js";
|
|
13
14
|
import { _shouldStreamForGlobalFetchImplementation, _getFetchImplementation, } from "./singletons/fetch.js";
|
|
14
15
|
import { serialize as serializePayloadForTracing } from "./utils/fast-safe-stringify/index.js";
|
|
15
16
|
export function mergeRuntimeEnvIntoRun(run, cachedEnvVars, omitTracedRuntimeInfo) {
|
|
@@ -397,6 +398,18 @@ export class Client {
|
|
|
397
398
|
writable: true,
|
|
398
399
|
value: getLangSmithEnvironmentVariable("DISABLE_RUN_COMPRESSION") === "true"
|
|
399
400
|
});
|
|
401
|
+
Object.defineProperty(this, "failedTracesDir", {
|
|
402
|
+
enumerable: true,
|
|
403
|
+
configurable: true,
|
|
404
|
+
writable: true,
|
|
405
|
+
value: void 0
|
|
406
|
+
});
|
|
407
|
+
Object.defineProperty(this, "failedTracesMaxBytes", {
|
|
408
|
+
enumerable: true,
|
|
409
|
+
configurable: true,
|
|
410
|
+
writable: true,
|
|
411
|
+
value: 100 * 1024 * 1024
|
|
412
|
+
});
|
|
400
413
|
Object.defineProperty(this, "debug", {
|
|
401
414
|
enumerable: true,
|
|
402
415
|
configurable: true,
|
|
@@ -428,6 +441,16 @@ export class Client {
|
|
|
428
441
|
}
|
|
429
442
|
this.debug = config.debug ?? this.debug;
|
|
430
443
|
this.fetchImplementation = config.fetchImplementation;
|
|
444
|
+
// Failed trace dump configuration
|
|
445
|
+
this.failedTracesDir =
|
|
446
|
+
getLangSmithEnvironmentVariable("FAILED_TRACES_DIR") || undefined;
|
|
447
|
+
const failedTracesMb = getLangSmithEnvironmentVariable("FAILED_TRACES_MAX_MB");
|
|
448
|
+
if (failedTracesMb) {
|
|
449
|
+
const n = parseInt(failedTracesMb, 10);
|
|
450
|
+
if (Number.isFinite(n) && n > 0) {
|
|
451
|
+
this.failedTracesMaxBytes = n * 1024 * 1024;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
431
454
|
// Use maxIngestMemoryBytes for both queues
|
|
432
455
|
const maxMemory = config.maxIngestMemoryBytes ?? DEFAULT_MAX_SIZE_BYTES;
|
|
433
456
|
this.batchIngestCaller = new AsyncCaller({
|
|
@@ -768,6 +791,63 @@ export class Client {
|
|
|
768
791
|
}
|
|
769
792
|
return Promise.all(promises);
|
|
770
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* Persist a failed trace payload to a local fallback directory.
|
|
796
|
+
*
|
|
797
|
+
* Saves a self-contained JSON file containing the endpoint path, the HTTP
|
|
798
|
+
* headers required for replay, and the base64-encoded request body.
|
|
799
|
+
* Can be replayed later with a simple POST:
|
|
800
|
+
*
|
|
801
|
+
* POST /<endpoint>
|
|
802
|
+
* Content-Type: <value from saved headers>
|
|
803
|
+
* [Content-Encoding: <value from saved headers>]
|
|
804
|
+
* <decoded body>
|
|
805
|
+
*/
|
|
806
|
+
static async _writeTraceToFallbackDir(directory, body, replayHeaders, endpoint, maxBytes) {
|
|
807
|
+
try {
|
|
808
|
+
const bodyBuffer = typeof body === "string"
|
|
809
|
+
? Buffer.from(body, "utf8")
|
|
810
|
+
: Buffer.from(body);
|
|
811
|
+
const envelope = JSON.stringify({
|
|
812
|
+
version: 1,
|
|
813
|
+
endpoint,
|
|
814
|
+
headers: replayHeaders,
|
|
815
|
+
body_base64: bodyBuffer.toString("base64"),
|
|
816
|
+
});
|
|
817
|
+
const filename = `trace_${Date.now()}_${uuid.v4().slice(0, 8)}.json`;
|
|
818
|
+
const filepath = fsUtils.path.join(directory, filename);
|
|
819
|
+
if (!Client._fallbackDirsCreated.has(directory)) {
|
|
820
|
+
await fsUtils.mkdir(directory);
|
|
821
|
+
Client._fallbackDirsCreated.add(directory);
|
|
822
|
+
}
|
|
823
|
+
// Check budget before writing — drop new traces if over limit.
|
|
824
|
+
if (maxBytes !== undefined && maxBytes > 0) {
|
|
825
|
+
try {
|
|
826
|
+
const entries = await fsUtils.readdir(directory);
|
|
827
|
+
const traceFiles = entries.filter((f) => f.startsWith("trace_") && f.endsWith(".json"));
|
|
828
|
+
let total = 0;
|
|
829
|
+
for (const name of traceFiles) {
|
|
830
|
+
const { size } = await fsUtils.stat(fsUtils.path.join(directory, name));
|
|
831
|
+
total += size;
|
|
832
|
+
}
|
|
833
|
+
if (total >= maxBytes) {
|
|
834
|
+
console.warn(`Could not write trace to fallback dir ${directory} as it's ` +
|
|
835
|
+
`already over size limit (${total} bytes >= ${maxBytes} bytes). ` +
|
|
836
|
+
`Increase LANGSMITH_FAILED_TRACES_MAX_MB if possible.`);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
catch {
|
|
841
|
+
// budget check errors must never prevent writing
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
await fsUtils.writeFileAtomic(filepath, envelope);
|
|
845
|
+
console.warn(`LangSmith trace upload failed; data saved to ${filepath} for later replay.`);
|
|
846
|
+
}
|
|
847
|
+
catch (writeErr) {
|
|
848
|
+
console.error(`LangSmith tracing error: could not write trace to fallback dir ${directory}:`, writeErr);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
771
851
|
async _processBatch(batch, options) {
|
|
772
852
|
if (!batch.length) {
|
|
773
853
|
return;
|
|
@@ -1348,6 +1428,12 @@ export class Client {
|
|
|
1348
1428
|
throw e;
|
|
1349
1429
|
}
|
|
1350
1430
|
console.warn(`${e.message.trim()}\n\nContext: ${context}`);
|
|
1431
|
+
if (this.failedTracesDir) {
|
|
1432
|
+
const bodyBuffer = await this._createNodeFetchBody(parts, boundary).catch(() => null);
|
|
1433
|
+
if (bodyBuffer) {
|
|
1434
|
+
await Client._writeTraceToFallbackDir(this.failedTracesDir, bodyBuffer, { "Content-Type": `multipart/form-data; boundary=${boundary}` }, "runs/multipart", this.failedTracesMaxBytes);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1351
1437
|
}
|
|
1352
1438
|
}
|
|
1353
1439
|
async updateRun(runId, run, options) {
|
|
@@ -1701,6 +1787,128 @@ export class Client {
|
|
|
1701
1787
|
}
|
|
1702
1788
|
}
|
|
1703
1789
|
}
|
|
1790
|
+
async *readThread(props) {
|
|
1791
|
+
const { threadId, projectId, projectName, isRoot = true, limit, filter: userFilter, order = "asc", } = props;
|
|
1792
|
+
if (!projectId && !projectName) {
|
|
1793
|
+
throw new Error("threadId requires projectId or projectName");
|
|
1794
|
+
}
|
|
1795
|
+
const threadFilter = `eq(thread_id, ${JSON.stringify(threadId)})`;
|
|
1796
|
+
const combinedFilter = userFilter
|
|
1797
|
+
? `and(${threadFilter}, ${userFilter})`
|
|
1798
|
+
: threadFilter;
|
|
1799
|
+
yield* this.listRuns({
|
|
1800
|
+
projectId: projectId ?? undefined,
|
|
1801
|
+
projectName: projectName ?? undefined,
|
|
1802
|
+
isRoot,
|
|
1803
|
+
limit,
|
|
1804
|
+
filter: combinedFilter,
|
|
1805
|
+
order,
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
async listThreads(props) {
|
|
1809
|
+
const { projectId, projectName, limit, offset = 0, filter, startTime, isRoot = true, } = props;
|
|
1810
|
+
if (!projectId && !projectName) {
|
|
1811
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
1812
|
+
}
|
|
1813
|
+
if (projectId && projectName) {
|
|
1814
|
+
throw new Error("Provide exactly one of projectId or projectName");
|
|
1815
|
+
}
|
|
1816
|
+
const sessionId = projectId ?? (await this.readProject({ projectName: projectName })).id;
|
|
1817
|
+
const startTimeResolved = startTime ?? new Date(Date.now() - 1 * 24 * 60 * 60 * 1000);
|
|
1818
|
+
const runSelect = [
|
|
1819
|
+
"id",
|
|
1820
|
+
"name",
|
|
1821
|
+
"status",
|
|
1822
|
+
"start_time",
|
|
1823
|
+
"end_time",
|
|
1824
|
+
"thread_id",
|
|
1825
|
+
"trace_id",
|
|
1826
|
+
"run_type",
|
|
1827
|
+
"error",
|
|
1828
|
+
"tags",
|
|
1829
|
+
"session_id",
|
|
1830
|
+
"parent_run_id",
|
|
1831
|
+
"total_tokens",
|
|
1832
|
+
"total_cost",
|
|
1833
|
+
"dotted_order",
|
|
1834
|
+
"reference_example_id",
|
|
1835
|
+
"feedback_stats",
|
|
1836
|
+
"app_path",
|
|
1837
|
+
"completion_cost",
|
|
1838
|
+
"completion_tokens",
|
|
1839
|
+
"prompt_cost",
|
|
1840
|
+
"prompt_tokens",
|
|
1841
|
+
"first_token_time",
|
|
1842
|
+
];
|
|
1843
|
+
const bodyQuery = {
|
|
1844
|
+
session: [sessionId],
|
|
1845
|
+
is_root: isRoot,
|
|
1846
|
+
limit: 100,
|
|
1847
|
+
order: "desc",
|
|
1848
|
+
select: runSelect,
|
|
1849
|
+
start_time: startTimeResolved.toISOString(),
|
|
1850
|
+
};
|
|
1851
|
+
if (filter != null) {
|
|
1852
|
+
bodyQuery.filter = filter;
|
|
1853
|
+
}
|
|
1854
|
+
const threadsMap = new Map();
|
|
1855
|
+
for await (const runs of this._getCursorPaginatedList("/runs/query", bodyQuery)) {
|
|
1856
|
+
for (const run of runs) {
|
|
1857
|
+
const tid = run.thread_id;
|
|
1858
|
+
if (tid) {
|
|
1859
|
+
const list = threadsMap.get(tid) ?? [];
|
|
1860
|
+
list.push(run);
|
|
1861
|
+
threadsMap.set(tid, list);
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
const result = [];
|
|
1866
|
+
for (const [threadId, runs] of threadsMap.entries()) {
|
|
1867
|
+
runs.sort((a, b) => {
|
|
1868
|
+
const aRun = a;
|
|
1869
|
+
const bRun = b;
|
|
1870
|
+
const aStart = aRun.start_time ?? "";
|
|
1871
|
+
const bStart = bRun.start_time ?? "";
|
|
1872
|
+
if (aStart !== bStart)
|
|
1873
|
+
return aStart.localeCompare(bStart);
|
|
1874
|
+
const aOrder = aRun.dotted_order ?? "";
|
|
1875
|
+
const bOrder = bRun.dotted_order ?? "";
|
|
1876
|
+
return aOrder.localeCompare(bOrder);
|
|
1877
|
+
});
|
|
1878
|
+
const startTimes = runs
|
|
1879
|
+
.map((r) => r.start_time)
|
|
1880
|
+
.filter(Boolean);
|
|
1881
|
+
const sortedTimes = [...startTimes].sort();
|
|
1882
|
+
const minStart = sortedTimes.length ? sortedTimes[0] : "";
|
|
1883
|
+
const maxStart = sortedTimes.length
|
|
1884
|
+
? sortedTimes[sortedTimes.length - 1]
|
|
1885
|
+
: "";
|
|
1886
|
+
result.push({
|
|
1887
|
+
thread_id: threadId,
|
|
1888
|
+
runs,
|
|
1889
|
+
count: runs.length,
|
|
1890
|
+
filter: "",
|
|
1891
|
+
total_tokens: 0,
|
|
1892
|
+
total_cost: null,
|
|
1893
|
+
min_start_time: minStart,
|
|
1894
|
+
max_start_time: maxStart,
|
|
1895
|
+
latency_p50: 0,
|
|
1896
|
+
latency_p99: 0,
|
|
1897
|
+
feedback_stats: null,
|
|
1898
|
+
first_inputs: "",
|
|
1899
|
+
last_outputs: "",
|
|
1900
|
+
last_error: null,
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
result.sort((a, b) => {
|
|
1904
|
+
const aMax = a.max_start_time ?? "";
|
|
1905
|
+
const bMax = b.max_start_time ?? "";
|
|
1906
|
+
return bMax.localeCompare(aMax);
|
|
1907
|
+
});
|
|
1908
|
+
const withOffset = offset > 0 ? result.slice(offset) : result;
|
|
1909
|
+
const withLimit = limit !== undefined ? withOffset.slice(0, limit) : withOffset;
|
|
1910
|
+
return withLimit;
|
|
1911
|
+
}
|
|
1704
1912
|
async getRunStats({ id, trace, parentRun, runType, projectNames, projectIds, referenceExampleIds, startTime, endTime, error, query, filter, traceFilter, treeFilter, isRoot, dataSourceType, }) {
|
|
1705
1913
|
let projectIds_ = projectIds || [];
|
|
1706
1914
|
if (projectNames) {
|
|
@@ -2949,7 +3157,7 @@ export class Client {
|
|
|
2949
3157
|
assertUuid(feedback_source.metadata["__run"].run_id);
|
|
2950
3158
|
}
|
|
2951
3159
|
const feedback = {
|
|
2952
|
-
id: feedbackId ?? uuid.
|
|
3160
|
+
id: feedbackId ?? uuid.v7(),
|
|
2953
3161
|
run_id: runId,
|
|
2954
3162
|
key,
|
|
2955
3163
|
score: _formatFeedbackScore(score),
|
|
@@ -3567,21 +3775,110 @@ export class Client {
|
|
|
3567
3775
|
}
|
|
3568
3776
|
}
|
|
3569
3777
|
}
|
|
3778
|
+
/**
|
|
3779
|
+
* Check if a prompt exists.
|
|
3780
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
3781
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
3782
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
3783
|
+
* @returns A Promise that resolves to true if the prompt exists, false otherwise
|
|
3784
|
+
* @example
|
|
3785
|
+
* ```typescript
|
|
3786
|
+
* // Check if a prompt exists before creating a commit
|
|
3787
|
+
* if (await client.promptExists("my-prompt")) {
|
|
3788
|
+
* await client.createCommit("my-prompt", template);
|
|
3789
|
+
* } else {
|
|
3790
|
+
* await client.createPrompt("my-prompt");
|
|
3791
|
+
* }
|
|
3792
|
+
* ```
|
|
3793
|
+
*/
|
|
3570
3794
|
async promptExists(promptIdentifier) {
|
|
3571
3795
|
const prompt = await this.getPrompt(promptIdentifier);
|
|
3572
3796
|
return !!prompt;
|
|
3573
3797
|
}
|
|
3798
|
+
/**
|
|
3799
|
+
* Like a prompt.
|
|
3800
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
3801
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
3802
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
3803
|
+
* @returns A Promise that resolves to the like response containing the updated like count
|
|
3804
|
+
* @example
|
|
3805
|
+
* ```typescript
|
|
3806
|
+
* // Like a prompt
|
|
3807
|
+
* const response = await client.likePrompt("owner/useful-prompt");
|
|
3808
|
+
* console.log(`Prompt now has ${response.likes} likes`);
|
|
3809
|
+
* ```
|
|
3810
|
+
*/
|
|
3574
3811
|
async likePrompt(promptIdentifier) {
|
|
3575
3812
|
return this._likeOrUnlikePrompt(promptIdentifier, true);
|
|
3576
3813
|
}
|
|
3814
|
+
/**
|
|
3815
|
+
* Unlike a prompt (remove a previously added like).
|
|
3816
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
3817
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
3818
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
3819
|
+
* @returns A Promise that resolves to the like response containing the updated like count
|
|
3820
|
+
* @example
|
|
3821
|
+
* ```typescript
|
|
3822
|
+
* // Unlike a prompt
|
|
3823
|
+
* const response = await client.unlikePrompt("owner/useful-prompt");
|
|
3824
|
+
* console.log(`Prompt now has ${response.likes} likes`);
|
|
3825
|
+
* ```
|
|
3826
|
+
*/
|
|
3577
3827
|
async unlikePrompt(promptIdentifier) {
|
|
3578
3828
|
return this._likeOrUnlikePrompt(promptIdentifier, false);
|
|
3579
3829
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
3830
|
+
/**
|
|
3831
|
+
* List all commits for a prompt.
|
|
3832
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
3833
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
3834
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
3835
|
+
* - "promptName:commitHash" (commit hash is ignored, all commits are returned)
|
|
3836
|
+
* @returns An async iterable iterator of PromptCommit objects
|
|
3837
|
+
* @example
|
|
3838
|
+
* ```typescript
|
|
3839
|
+
* // List commits for a private prompt
|
|
3840
|
+
* for await (const commit of client.listCommits("my-prompt")) {
|
|
3841
|
+
* console.log(commit);
|
|
3842
|
+
* }
|
|
3843
|
+
*
|
|
3844
|
+
* // List commits for a prompt with explicit owner
|
|
3845
|
+
* for await (const commit of client.listCommits("owner/my-prompt")) {
|
|
3846
|
+
* console.log(commit);
|
|
3847
|
+
* }
|
|
3848
|
+
* ```
|
|
3849
|
+
*/
|
|
3850
|
+
async *listCommits(promptIdentifier) {
|
|
3851
|
+
const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
|
|
3852
|
+
for await (const commits of this._getPaginated(`/commits/${owner}/${promptName}/`, new URLSearchParams(), (res) => res.commits)) {
|
|
3582
3853
|
yield* commits;
|
|
3583
3854
|
}
|
|
3584
3855
|
}
|
|
3856
|
+
/**
|
|
3857
|
+
* List prompts by filter.
|
|
3858
|
+
* @param options - Optional filters for listing prompts
|
|
3859
|
+
* @param options.isPublic - Filter by public/private prompts. If undefined, returns all prompts.
|
|
3860
|
+
* @param options.isArchived - Filter by archived status. Defaults to false (non-archived prompts only).
|
|
3861
|
+
* @param options.sortField - Field to sort by. Defaults to "updated_at".
|
|
3862
|
+
* @param options.query - Search query to filter prompts by name or description.
|
|
3863
|
+
* @returns An async iterable iterator of Prompt objects
|
|
3864
|
+
* @example
|
|
3865
|
+
* ```typescript
|
|
3866
|
+
* // List all prompts
|
|
3867
|
+
* for await (const prompt of client.listPrompts()) {
|
|
3868
|
+
* console.log(prompt);
|
|
3869
|
+
* }
|
|
3870
|
+
*
|
|
3871
|
+
* // List only public prompts
|
|
3872
|
+
* for await (const prompt of client.listPrompts({ isPublic: true })) {
|
|
3873
|
+
* console.log(prompt);
|
|
3874
|
+
* }
|
|
3875
|
+
*
|
|
3876
|
+
* // Search for prompts
|
|
3877
|
+
* for await (const prompt of client.listPrompts({ query: "translation" })) {
|
|
3878
|
+
* console.log(prompt);
|
|
3879
|
+
* }
|
|
3880
|
+
* ```
|
|
3881
|
+
*/
|
|
3585
3882
|
async *listPrompts(options) {
|
|
3586
3883
|
const params = new URLSearchParams();
|
|
3587
3884
|
params.append("sort_field", options?.sortField ?? "updated_at");
|
|
@@ -3597,6 +3894,22 @@ export class Client {
|
|
|
3597
3894
|
yield* prompts;
|
|
3598
3895
|
}
|
|
3599
3896
|
}
|
|
3897
|
+
/**
|
|
3898
|
+
* Get a prompt by its identifier.
|
|
3899
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
3900
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
3901
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
3902
|
+
* - "promptName:commitHash" (commit hash is ignored, latest version is returned)
|
|
3903
|
+
* @returns A Promise that resolves to the Prompt object, or null if not found
|
|
3904
|
+
* @example
|
|
3905
|
+
* ```typescript
|
|
3906
|
+
* // Get a private prompt
|
|
3907
|
+
* const prompt = await client.getPrompt("my-prompt");
|
|
3908
|
+
*
|
|
3909
|
+
* // Get a public prompt
|
|
3910
|
+
* const publicPrompt = await client.getPrompt("owner/public-prompt");
|
|
3911
|
+
* ```
|
|
3912
|
+
*/
|
|
3600
3913
|
async getPrompt(promptIdentifier) {
|
|
3601
3914
|
const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
|
|
3602
3915
|
const response = await this.caller.call(async () => {
|
|
@@ -3620,6 +3933,33 @@ export class Client {
|
|
|
3620
3933
|
return null;
|
|
3621
3934
|
}
|
|
3622
3935
|
}
|
|
3936
|
+
/**
|
|
3937
|
+
* Create a new prompt.
|
|
3938
|
+
* @param promptIdentifier - The identifier for the new prompt. Can be in the format:
|
|
3939
|
+
* - "promptName" (creates a private prompt)
|
|
3940
|
+
* - "owner/promptName" (creates a prompt under a specific owner, must match your tenant)
|
|
3941
|
+
* @param options - Optional configuration for the prompt
|
|
3942
|
+
* @param options.description - A description of the prompt
|
|
3943
|
+
* @param options.readme - Markdown content for the prompt's README
|
|
3944
|
+
* @param options.tags - Array of tags to categorize the prompt
|
|
3945
|
+
* @param options.isPublic - Whether the prompt should be public. Requires a LangChain Hub handle.
|
|
3946
|
+
* @returns A Promise that resolves to the created Prompt object
|
|
3947
|
+
* @throws {Error} If creating a public prompt without a LangChain Hub handle, or if owner doesn't match current tenant
|
|
3948
|
+
* @example
|
|
3949
|
+
* ```typescript
|
|
3950
|
+
* // Create a private prompt
|
|
3951
|
+
* const prompt = await client.createPrompt("my-new-prompt", {
|
|
3952
|
+
* description: "A prompt for translations",
|
|
3953
|
+
* tags: ["translation", "language"]
|
|
3954
|
+
* });
|
|
3955
|
+
*
|
|
3956
|
+
* // Create a public prompt
|
|
3957
|
+
* const publicPrompt = await client.createPrompt("my-public-prompt", {
|
|
3958
|
+
* description: "A public translation prompt",
|
|
3959
|
+
* isPublic: true
|
|
3960
|
+
* });
|
|
3961
|
+
* ```
|
|
3962
|
+
*/
|
|
3623
3963
|
async createPrompt(promptIdentifier, options) {
|
|
3624
3964
|
const settings = await this._getSettings();
|
|
3625
3965
|
if (options?.isPublic && !settings.tenant_handle) {
|
|
@@ -3654,6 +3994,35 @@ export class Client {
|
|
|
3654
3994
|
const { repo } = await response.json();
|
|
3655
3995
|
return repo;
|
|
3656
3996
|
}
|
|
3997
|
+
/**
|
|
3998
|
+
* Create a new commit for an existing prompt.
|
|
3999
|
+
* @param promptIdentifier - The identifier of the prompt. Can be in the format:
|
|
4000
|
+
* - "promptName" (for private prompts, owner defaults to "-")
|
|
4001
|
+
* - "owner/promptName" (for prompts with explicit owner)
|
|
4002
|
+
* @param object - The prompt object/manifest to commit (e.g., ChatPromptTemplate, messages array, etc.)
|
|
4003
|
+
* @param options - Optional configuration for the commit
|
|
4004
|
+
* @param options.parentCommitHash - The parent commit hash. Defaults to "latest" (the most recent commit).
|
|
4005
|
+
* @returns A Promise that resolves to the URL of the newly created commit
|
|
4006
|
+
* @throws {Error} If the prompt does not exist
|
|
4007
|
+
* @example
|
|
4008
|
+
* ```typescript
|
|
4009
|
+
* import { ChatPromptTemplate } from "@langchain/core/prompts";
|
|
4010
|
+
*
|
|
4011
|
+
* // Create a commit with a new version of the prompt
|
|
4012
|
+
* const template = ChatPromptTemplate.fromMessages([
|
|
4013
|
+
* ["system", "You are a helpful assistant."],
|
|
4014
|
+
* ["human", "{input}"]
|
|
4015
|
+
* ]);
|
|
4016
|
+
*
|
|
4017
|
+
* const commitUrl = await client.createCommit("my-prompt", template);
|
|
4018
|
+
* console.log(`Commit created: ${commitUrl}`);
|
|
4019
|
+
*
|
|
4020
|
+
* // Create a commit based on a specific parent commit
|
|
4021
|
+
* const commitUrl2 = await client.createCommit("my-prompt", template, {
|
|
4022
|
+
* parentCommitHash: "abc123def456"
|
|
4023
|
+
* });
|
|
4024
|
+
* ```
|
|
4025
|
+
*/
|
|
3657
4026
|
async createCommit(promptIdentifier, object, options) {
|
|
3658
4027
|
if (!(await this.promptExists(promptIdentifier))) {
|
|
3659
4028
|
throw new Error("Prompt does not exist, you must create it first.");
|
|
@@ -4137,6 +4506,12 @@ export class Client {
|
|
|
4137
4506
|
}
|
|
4138
4507
|
}
|
|
4139
4508
|
}
|
|
4509
|
+
Object.defineProperty(Client, "_fallbackDirsCreated", {
|
|
4510
|
+
enumerable: true,
|
|
4511
|
+
configurable: true,
|
|
4512
|
+
writable: true,
|
|
4513
|
+
value: new Set()
|
|
4514
|
+
});
|
|
4140
4515
|
function isExampleCreate(input) {
|
|
4141
4516
|
return "dataset_id" in input || "dataset_name" in input;
|
|
4142
4517
|
}
|
|
@@ -67,7 +67,7 @@ class DynamicRunEvaluator {
|
|
|
67
67
|
* @returns A promise that extracts to the evaluation result.
|
|
68
68
|
*/
|
|
69
69
|
async evaluateRun(run, example, options) {
|
|
70
|
-
let sourceRunId = (0, uuid_1.
|
|
70
|
+
let sourceRunId = (0, uuid_1.v7)();
|
|
71
71
|
const metadata = {
|
|
72
72
|
targetRunId: run.id,
|
|
73
73
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v7 as uuidv7 } from "uuid";
|
|
2
2
|
import { traceable } from "../traceable.js";
|
|
3
3
|
/**
|
|
4
4
|
* Wraps an evaluator function + implements the RunEvaluator interface.
|
|
@@ -63,7 +63,7 @@ export class DynamicRunEvaluator {
|
|
|
63
63
|
* @returns A promise that extracts to the evaluation result.
|
|
64
64
|
*/
|
|
65
65
|
async evaluateRun(run, example, options) {
|
|
66
|
-
let sourceRunId =
|
|
66
|
+
let sourceRunId = uuidv7();
|
|
67
67
|
const metadata = {
|
|
68
68
|
targetRunId: run.id,
|
|
69
69
|
};
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapClaudeAgentSDK = wrapClaudeAgentSDK;
|
|
4
|
+
const module_1 = require("module");
|
|
4
5
|
const traceable_js_1 = require("../../traceable.cjs");
|
|
5
6
|
const context_js_1 = require("./context.cjs");
|
|
6
7
|
const messages_js_1 = require("./messages.cjs");
|
|
8
|
+
function _getPackageVersion(packageName) {
|
|
9
|
+
try {
|
|
10
|
+
const req = (0, module_1.createRequire)(process.cwd() + "/package.json");
|
|
11
|
+
return req(`${packageName}/package.json`).version;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
7
17
|
/**
|
|
8
18
|
* Wraps the Claude Agent SDK's query function to add LangSmith tracing.
|
|
9
19
|
* Traces the entire agent interaction including all streaming messages.
|
|
@@ -110,7 +120,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis, baseConfig) {
|
|
|
110
120
|
name: "claude.conversation",
|
|
111
121
|
run_type: "chain",
|
|
112
122
|
...baseConfig,
|
|
113
|
-
metadata: {
|
|
123
|
+
metadata: {
|
|
124
|
+
ls_integration: "claude-agent-sdk",
|
|
125
|
+
ls_integration_version: _getPackageVersion("@anthropic-ai/claude-agent-sdk"),
|
|
126
|
+
...baseConfig?.metadata,
|
|
127
|
+
},
|
|
114
128
|
__deferredSerializableArgOptions: { maxDepth: 1 },
|
|
115
129
|
processInputs,
|
|
116
130
|
processOutputs,
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
1
2
|
import { traceable, isTraceableFunction } from "../../traceable.js";
|
|
2
3
|
import { StreamManager } from "./context.js";
|
|
3
4
|
import { convertFromAnthropicMessage } from "./messages.js";
|
|
5
|
+
function _getPackageVersion(packageName) {
|
|
6
|
+
try {
|
|
7
|
+
const req = createRequire(process.cwd() + "/package.json");
|
|
8
|
+
return req(`${packageName}/package.json`).version;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
4
14
|
/**
|
|
5
15
|
* Wraps the Claude Agent SDK's query function to add LangSmith tracing.
|
|
6
16
|
* Traces the entire agent interaction including all streaming messages.
|
|
@@ -107,7 +117,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis, baseConfig) {
|
|
|
107
117
|
name: "claude.conversation",
|
|
108
118
|
run_type: "chain",
|
|
109
119
|
...baseConfig,
|
|
110
|
-
metadata: {
|
|
120
|
+
metadata: {
|
|
121
|
+
ls_integration: "claude-agent-sdk",
|
|
122
|
+
ls_integration_version: _getPackageVersion("@anthropic-ai/claude-agent-sdk"),
|
|
123
|
+
...baseConfig?.metadata,
|
|
124
|
+
},
|
|
111
125
|
__deferredSerializableArgOptions: { maxDepth: 1 },
|
|
112
126
|
processInputs,
|
|
113
127
|
processOutputs,
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.convertMessageToTracedFormat = exports.wrapAISDK = exports.createLangSmithProviderOptions = void 0;
|
|
4
|
+
const module_1 = require("module");
|
|
5
|
+
function _getPackageVersion(packageName) {
|
|
6
|
+
try {
|
|
7
|
+
const req = (0, module_1.createRequire)(process.cwd() + "/package.json");
|
|
8
|
+
return req(`${packageName}/package.json`).version;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
4
14
|
const middleware_js_1 = require("./middleware.cjs");
|
|
5
15
|
const utils_js_1 = require("./utils.cjs");
|
|
6
16
|
Object.defineProperty(exports, "convertMessageToTracedFormat", { enumerable: true, get: function () { return utils_js_1.convertMessageToTracedFormat; } });
|
|
@@ -305,6 +315,14 @@ exports.createLangSmithProviderOptions = createLangSmithProviderOptions;
|
|
|
305
315
|
* @returns returns.streamObject - Wrapped streamObject function that traces calls to LangSmith
|
|
306
316
|
*/
|
|
307
317
|
const wrapAISDK = (ai, baseLsConfig) => {
|
|
318
|
+
const _baseLsConfig = {
|
|
319
|
+
...baseLsConfig,
|
|
320
|
+
metadata: {
|
|
321
|
+
ls_integration: "vercel-ai-sdk",
|
|
322
|
+
ls_integration_version: _getPackageVersion("ai"),
|
|
323
|
+
...baseLsConfig?.metadata,
|
|
324
|
+
},
|
|
325
|
+
};
|
|
308
326
|
/**
|
|
309
327
|
* Wrapped version of AI SDK's generateText with LangSmith tracing.
|
|
310
328
|
*
|
|
@@ -326,7 +344,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
326
344
|
const wrappedGenerateText = async (...args) => {
|
|
327
345
|
const params = args[0];
|
|
328
346
|
const { langsmith: runtimeLsConfig, ...providerOptions } = params.providerOptions ?? {};
|
|
329
|
-
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig } = _resolveConfigs(
|
|
347
|
+
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig } = _resolveConfigs(_baseLsConfig, runtimeLsConfig);
|
|
330
348
|
const hasExplicitOutput = "output" in params;
|
|
331
349
|
const hasExplicitExperimentalOutput = "experimental_output" in params;
|
|
332
350
|
const traceableFunc = (0, traceable_js_1.traceable)(async (...args) => {
|
|
@@ -378,7 +396,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
378
396
|
wrappedGenerateObject = async (...args) => {
|
|
379
397
|
const params = args[0];
|
|
380
398
|
const { langsmith: runtimeLsConfig, ...providerOptions } = params.providerOptions ?? {};
|
|
381
|
-
const { resolvedLsConfig, resolvedChildLLMRunConfig } = _resolveConfigs(
|
|
399
|
+
const { resolvedLsConfig, resolvedChildLLMRunConfig } = _resolveConfigs(_baseLsConfig, runtimeLsConfig);
|
|
382
400
|
const traceableFunc = (0, traceable_js_1.traceable)(async (...args) => {
|
|
383
401
|
const [params, ...rest] = args;
|
|
384
402
|
const wrappedModel = ai.wrapLanguageModel({
|
|
@@ -446,7 +464,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
446
464
|
const wrappedStreamText = (...args) => {
|
|
447
465
|
const params = args[0];
|
|
448
466
|
const { langsmith: runtimeLsConfig, ...providerOptions } = params.providerOptions ?? {};
|
|
449
|
-
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig } = _resolveConfigs(
|
|
467
|
+
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig } = _resolveConfigs(_baseLsConfig, runtimeLsConfig);
|
|
450
468
|
const hasExplicitOutput = "output" in params;
|
|
451
469
|
const hasExplicitExperimentalOutput = "experimental_output" in params;
|
|
452
470
|
const traceableFunc = (0, traceable_js_1.traceable)((...args) => {
|
|
@@ -499,7 +517,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
499
517
|
wrappedStreamObject = (...args) => {
|
|
500
518
|
const params = args[0];
|
|
501
519
|
const { langsmith: runtimeLsConfig, ...providerOptions } = params.providerOptions ?? {};
|
|
502
|
-
const { resolvedLsConfig, resolvedChildLLMRunConfig } = _resolveConfigs(
|
|
520
|
+
const { resolvedLsConfig, resolvedChildLLMRunConfig } = _resolveConfigs(_baseLsConfig, runtimeLsConfig);
|
|
503
521
|
const traceableFunc = (0, traceable_js_1.traceable)((...args) => {
|
|
504
522
|
const [params, ...rest] = args;
|
|
505
523
|
const wrappedModel = ai.wrapLanguageModel({
|
|
@@ -563,7 +581,7 @@ const wrapAISDK = (ai, baseLsConfig) => {
|
|
|
563
581
|
construct(ToolLoopAgent, args) {
|
|
564
582
|
const params = args[0] ?? {};
|
|
565
583
|
const { langsmith: runtimeLsConfig } = params.providerOptions ?? {};
|
|
566
|
-
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig, } = _resolveConfigs(
|
|
584
|
+
const { resolvedLsConfig, resolvedChildLLMRunConfig, resolvedToolConfig, } = _resolveConfigs(_baseLsConfig, runtimeLsConfig);
|
|
567
585
|
let wrappedModel = params.model;
|
|
568
586
|
if (wrappedModel != null) {
|
|
569
587
|
wrappedModel = ai.wrapLanguageModel({
|