langsmith 0.4.3 → 0.4.5
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 +19 -41
- package/dist/client.d.ts +25 -30
- package/dist/client.js +20 -42
- package/dist/index.cjs +4 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/run_trees.cjs +6 -7
- package/dist/run_trees.js +7 -8
- package/dist/utils/_uuid.cjs +0 -87
- package/dist/utils/_uuid.d.ts +0 -26
- package/dist/utils/_uuid.js +0 -86
- package/dist/utils/prompts_cache.cjs +12 -68
- package/dist/utils/prompts_cache.d.ts +8 -5
- package/dist/utils/prompts_cache.js +10 -33
- package/dist/utils/prompts_cache_fs.browser.cjs +24 -0
- package/dist/utils/prompts_cache_fs.browser.d.ts +16 -0
- package/dist/utils/prompts_cache_fs.browser.js +20 -0
- package/dist/utils/prompts_cache_fs.cjs +86 -0
- package/dist/utils/prompts_cache_fs.d.ts +16 -0
- package/dist/utils/prompts_cache_fs.js +49 -0
- package/package.json +4 -1
package/dist/client.cjs
CHANGED
|
@@ -411,7 +411,7 @@ class Client {
|
|
|
411
411
|
writable: true,
|
|
412
412
|
value: void 0
|
|
413
413
|
});
|
|
414
|
-
Object.defineProperty(this, "
|
|
414
|
+
Object.defineProperty(this, "_cache", {
|
|
415
415
|
enumerable: true,
|
|
416
416
|
configurable: true,
|
|
417
417
|
writable: true,
|
|
@@ -488,26 +488,15 @@ class Client {
|
|
|
488
488
|
}
|
|
489
489
|
// Cache metadata env vars once during construction to avoid repeatedly scanning process.env
|
|
490
490
|
this.cachedLSEnvVarsForMetadata = (0, env_js_1.getLangSmithEnvVarsMetadata)();
|
|
491
|
-
// Initialize
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
"3600"),
|
|
501
|
-
refreshIntervalSeconds: config.promptCacheRefreshIntervalSeconds ??
|
|
502
|
-
parseFloat((0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_REFRESH_INTERVAL_SECONDS") ?? "60"),
|
|
503
|
-
fetchFunc: this._makeFetchPromptFunc(),
|
|
504
|
-
});
|
|
505
|
-
// Load from file if path provided
|
|
506
|
-
const cachePath = config.promptCachePath ??
|
|
507
|
-
(0, env_js_1.getLangSmithEnvironmentVariable)("PROMPT_CACHE_PATH");
|
|
508
|
-
if (cachePath) {
|
|
509
|
-
this._promptCache.load(cachePath);
|
|
510
|
-
}
|
|
491
|
+
// Initialize cache
|
|
492
|
+
if (config.cache === true) {
|
|
493
|
+
this._cache = new prompts_cache_js_1.Cache();
|
|
494
|
+
}
|
|
495
|
+
else if (config.cache && typeof config.cache === "object") {
|
|
496
|
+
this._cache = config.cache;
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
this._cache = undefined;
|
|
511
500
|
}
|
|
512
501
|
}
|
|
513
502
|
static getDefaultClientConfig() {
|
|
@@ -3820,17 +3809,6 @@ class Client {
|
|
|
3820
3809
|
const suffix = includeModel ? ":with_model" : "";
|
|
3821
3810
|
return `${promptIdentifier}${suffix}`;
|
|
3822
3811
|
}
|
|
3823
|
-
/**
|
|
3824
|
-
* Create a fetch function for the prompt cache to use for background refresh.
|
|
3825
|
-
*/
|
|
3826
|
-
_makeFetchPromptFunc() {
|
|
3827
|
-
return async (key) => {
|
|
3828
|
-
// Parse the cache key back to identifier and options
|
|
3829
|
-
const includeModel = key.endsWith(":with_model");
|
|
3830
|
-
const identifier = includeModel ? key.slice(0, -11) : key; // Remove ":with_model"
|
|
3831
|
-
return this._fetchPromptFromApi(identifier, { includeModel });
|
|
3832
|
-
};
|
|
3833
|
-
}
|
|
3834
3812
|
/**
|
|
3835
3813
|
* Fetch a prompt commit directly from the API (bypassing cache).
|
|
3836
3814
|
*/
|
|
@@ -3857,15 +3835,15 @@ class Client {
|
|
|
3857
3835
|
}
|
|
3858
3836
|
async pullPromptCommit(promptIdentifier, options) {
|
|
3859
3837
|
// Check cache first if not skipped
|
|
3860
|
-
if (!options?.skipCache && this.
|
|
3838
|
+
if (!options?.skipCache && this._cache) {
|
|
3861
3839
|
const cacheKey = this._getPromptCacheKey(promptIdentifier, options?.includeModel);
|
|
3862
|
-
const cached = this.
|
|
3840
|
+
const cached = this._cache.get(cacheKey);
|
|
3863
3841
|
if (cached) {
|
|
3864
3842
|
return cached;
|
|
3865
3843
|
}
|
|
3866
3844
|
// Cache miss - fetch from API and cache it
|
|
3867
3845
|
const result = await this._fetchPromptFromApi(promptIdentifier, options);
|
|
3868
|
-
this.
|
|
3846
|
+
this._cache.set(cacheKey, result);
|
|
3869
3847
|
return result;
|
|
3870
3848
|
}
|
|
3871
3849
|
// No cache or skip cache - fetch directly
|
|
@@ -3995,19 +3973,19 @@ class Client {
|
|
|
3995
3973
|
}
|
|
3996
3974
|
}
|
|
3997
3975
|
/**
|
|
3998
|
-
* Get the
|
|
3976
|
+
* Get the cache instance, if caching is enabled.
|
|
3999
3977
|
* Useful for accessing cache metrics or manually managing the cache.
|
|
4000
3978
|
*/
|
|
4001
|
-
get
|
|
4002
|
-
return this.
|
|
3979
|
+
get cache() {
|
|
3980
|
+
return this._cache;
|
|
4003
3981
|
}
|
|
4004
3982
|
/**
|
|
4005
3983
|
* Cleanup resources held by the client.
|
|
4006
|
-
* Stops the
|
|
3984
|
+
* Stops the cache's background refresh timer.
|
|
4007
3985
|
*/
|
|
4008
3986
|
cleanup() {
|
|
4009
|
-
if (this.
|
|
4010
|
-
this.
|
|
3987
|
+
if (this._cache) {
|
|
3988
|
+
this._cache.stop();
|
|
4011
3989
|
}
|
|
4012
3990
|
}
|
|
4013
3991
|
/**
|
package/dist/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { OTELContext } from "./experimental/otel/types.js";
|
|
|
2
2
|
import { AsyncCallerParams } from "./utils/async_caller.js";
|
|
3
3
|
import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleCreate, ExampleUpdate, ExampleUpdateWithoutId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments, UploadExamplesResponse, UpdateExamplesResponse, DatasetVersion, AnnotationQueueWithDetails } from "./schemas.js";
|
|
4
4
|
import { EvaluationResult, EvaluationResults } from "./evaluation/evaluator.js";
|
|
5
|
-
import {
|
|
5
|
+
import { Cache } from "./utils/prompts_cache.js";
|
|
6
6
|
export interface ClientConfig {
|
|
7
7
|
apiUrl?: string;
|
|
8
8
|
apiKey?: string;
|
|
@@ -51,28 +51,27 @@ export interface ClientConfig {
|
|
|
51
51
|
*/
|
|
52
52
|
fetchImplementation?: typeof fetch;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
*
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*
|
|
73
|
-
* Useful for offline mode.
|
|
54
|
+
* Configuration for caching. Can be:
|
|
55
|
+
* - `true`: Enable caching with default settings
|
|
56
|
+
* - `Cache` instance: Use custom cache configuration
|
|
57
|
+
* - `undefined` or `false`: Disable caching (default)
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import { Client, Cache } from "langsmith";
|
|
62
|
+
*
|
|
63
|
+
* // Enable with defaults
|
|
64
|
+
* const client1 = new Client({ cache: true });
|
|
65
|
+
*
|
|
66
|
+
* // Or use custom configuration
|
|
67
|
+
* const myCache = new Cache({
|
|
68
|
+
* maxSize: 100,
|
|
69
|
+
* ttlSeconds: 3600, // 1 hour, or null for infinite TTL
|
|
70
|
+
* });
|
|
71
|
+
* const client2 = new Client({ cache: myCache });
|
|
72
|
+
* ```
|
|
74
73
|
*/
|
|
75
|
-
|
|
74
|
+
cache?: Cache | boolean;
|
|
76
75
|
}
|
|
77
76
|
/**
|
|
78
77
|
* Represents the parameters for listing runs (spans) from the Langsmith server.
|
|
@@ -375,7 +374,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
375
374
|
private langSmithToOTELTranslator?;
|
|
376
375
|
private fetchImplementation?;
|
|
377
376
|
private cachedLSEnvVarsForMetadata?;
|
|
378
|
-
private
|
|
377
|
+
private _cache?;
|
|
379
378
|
private get _fetch();
|
|
380
379
|
private multipartStreamingDisabled;
|
|
381
380
|
private _multipartDisabled;
|
|
@@ -1025,10 +1024,6 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
1025
1024
|
* Format: "{identifier}" or "{identifier}:with_model"
|
|
1026
1025
|
*/
|
|
1027
1026
|
private _getPromptCacheKey;
|
|
1028
|
-
/**
|
|
1029
|
-
* Create a fetch function for the prompt cache to use for background refresh.
|
|
1030
|
-
*/
|
|
1031
|
-
private _makeFetchPromptFunc;
|
|
1032
1027
|
/**
|
|
1033
1028
|
* Fetch a prompt commit directly from the API (bypassing cache).
|
|
1034
1029
|
*/
|
|
@@ -1071,13 +1066,13 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
1071
1066
|
}): Promise<void>;
|
|
1072
1067
|
private parseTokenOrUrl;
|
|
1073
1068
|
/**
|
|
1074
|
-
* Get the
|
|
1069
|
+
* Get the cache instance, if caching is enabled.
|
|
1075
1070
|
* Useful for accessing cache metrics or manually managing the cache.
|
|
1076
1071
|
*/
|
|
1077
|
-
get
|
|
1072
|
+
get cache(): Cache | undefined;
|
|
1078
1073
|
/**
|
|
1079
1074
|
* Cleanup resources held by the client.
|
|
1080
|
-
* Stops the
|
|
1075
|
+
* Stops the cache's background refresh timer.
|
|
1081
1076
|
*/
|
|
1082
1077
|
cleanup(): void;
|
|
1083
1078
|
/**
|
package/dist/client.js
CHANGED
|
@@ -9,7 +9,7 @@ import { assertUuid } from "./utils/_uuid.js";
|
|
|
9
9
|
import { warnOnce } from "./utils/warn.js";
|
|
10
10
|
import { parsePromptIdentifier } from "./utils/prompts.js";
|
|
11
11
|
import { raiseForStatus, isLangSmithNotFoundError } from "./utils/error.js";
|
|
12
|
-
import {
|
|
12
|
+
import { Cache } from "./utils/prompts_cache.js";
|
|
13
13
|
import { _globalFetchImplementationIsNodeFetch, _getFetchImplementation, } from "./singletons/fetch.js";
|
|
14
14
|
import { serialize as serializePayloadForTracing } from "./utils/fast-safe-stringify/index.js";
|
|
15
15
|
export function mergeRuntimeEnvIntoRun(run, cachedEnvVars, omitTracedRuntimeInfo) {
|
|
@@ -373,7 +373,7 @@ export class Client {
|
|
|
373
373
|
writable: true,
|
|
374
374
|
value: void 0
|
|
375
375
|
});
|
|
376
|
-
Object.defineProperty(this, "
|
|
376
|
+
Object.defineProperty(this, "_cache", {
|
|
377
377
|
enumerable: true,
|
|
378
378
|
configurable: true,
|
|
379
379
|
writable: true,
|
|
@@ -450,26 +450,15 @@ export class Client {
|
|
|
450
450
|
}
|
|
451
451
|
// Cache metadata env vars once during construction to avoid repeatedly scanning process.env
|
|
452
452
|
this.cachedLSEnvVarsForMetadata = getLangSmithEnvVarsMetadata();
|
|
453
|
-
// Initialize
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
"3600"),
|
|
463
|
-
refreshIntervalSeconds: config.promptCacheRefreshIntervalSeconds ??
|
|
464
|
-
parseFloat(getLangSmithEnvironmentVariable("PROMPT_CACHE_REFRESH_INTERVAL_SECONDS") ?? "60"),
|
|
465
|
-
fetchFunc: this._makeFetchPromptFunc(),
|
|
466
|
-
});
|
|
467
|
-
// Load from file if path provided
|
|
468
|
-
const cachePath = config.promptCachePath ??
|
|
469
|
-
getLangSmithEnvironmentVariable("PROMPT_CACHE_PATH");
|
|
470
|
-
if (cachePath) {
|
|
471
|
-
this._promptCache.load(cachePath);
|
|
472
|
-
}
|
|
453
|
+
// Initialize cache
|
|
454
|
+
if (config.cache === true) {
|
|
455
|
+
this._cache = new Cache();
|
|
456
|
+
}
|
|
457
|
+
else if (config.cache && typeof config.cache === "object") {
|
|
458
|
+
this._cache = config.cache;
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
this._cache = undefined;
|
|
473
462
|
}
|
|
474
463
|
}
|
|
475
464
|
static getDefaultClientConfig() {
|
|
@@ -3782,17 +3771,6 @@ export class Client {
|
|
|
3782
3771
|
const suffix = includeModel ? ":with_model" : "";
|
|
3783
3772
|
return `${promptIdentifier}${suffix}`;
|
|
3784
3773
|
}
|
|
3785
|
-
/**
|
|
3786
|
-
* Create a fetch function for the prompt cache to use for background refresh.
|
|
3787
|
-
*/
|
|
3788
|
-
_makeFetchPromptFunc() {
|
|
3789
|
-
return async (key) => {
|
|
3790
|
-
// Parse the cache key back to identifier and options
|
|
3791
|
-
const includeModel = key.endsWith(":with_model");
|
|
3792
|
-
const identifier = includeModel ? key.slice(0, -11) : key; // Remove ":with_model"
|
|
3793
|
-
return this._fetchPromptFromApi(identifier, { includeModel });
|
|
3794
|
-
};
|
|
3795
|
-
}
|
|
3796
3774
|
/**
|
|
3797
3775
|
* Fetch a prompt commit directly from the API (bypassing cache).
|
|
3798
3776
|
*/
|
|
@@ -3819,15 +3797,15 @@ export class Client {
|
|
|
3819
3797
|
}
|
|
3820
3798
|
async pullPromptCommit(promptIdentifier, options) {
|
|
3821
3799
|
// Check cache first if not skipped
|
|
3822
|
-
if (!options?.skipCache && this.
|
|
3800
|
+
if (!options?.skipCache && this._cache) {
|
|
3823
3801
|
const cacheKey = this._getPromptCacheKey(promptIdentifier, options?.includeModel);
|
|
3824
|
-
const cached = this.
|
|
3802
|
+
const cached = this._cache.get(cacheKey);
|
|
3825
3803
|
if (cached) {
|
|
3826
3804
|
return cached;
|
|
3827
3805
|
}
|
|
3828
3806
|
// Cache miss - fetch from API and cache it
|
|
3829
3807
|
const result = await this._fetchPromptFromApi(promptIdentifier, options);
|
|
3830
|
-
this.
|
|
3808
|
+
this._cache.set(cacheKey, result);
|
|
3831
3809
|
return result;
|
|
3832
3810
|
}
|
|
3833
3811
|
// No cache or skip cache - fetch directly
|
|
@@ -3957,19 +3935,19 @@ export class Client {
|
|
|
3957
3935
|
}
|
|
3958
3936
|
}
|
|
3959
3937
|
/**
|
|
3960
|
-
* Get the
|
|
3938
|
+
* Get the cache instance, if caching is enabled.
|
|
3961
3939
|
* Useful for accessing cache metrics or manually managing the cache.
|
|
3962
3940
|
*/
|
|
3963
|
-
get
|
|
3964
|
-
return this.
|
|
3941
|
+
get cache() {
|
|
3942
|
+
return this._cache;
|
|
3965
3943
|
}
|
|
3966
3944
|
/**
|
|
3967
3945
|
* Cleanup resources held by the client.
|
|
3968
|
-
* Stops the
|
|
3946
|
+
* Stops the cache's background refresh timer.
|
|
3969
3947
|
*/
|
|
3970
3948
|
cleanup() {
|
|
3971
|
-
if (this.
|
|
3972
|
-
this.
|
|
3949
|
+
if (this._cache) {
|
|
3950
|
+
this._cache.stop();
|
|
3973
3951
|
}
|
|
3974
3952
|
}
|
|
3975
3953
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.__version__ = exports.uuid7FromTime = exports.uuid7 = exports.getDefaultProjectName = exports.overrideFetchImplementation = exports.RunTree = exports.Client = void 0;
|
|
3
|
+
exports.__version__ = exports.Cache = exports.uuid7FromTime = exports.uuid7 = exports.getDefaultProjectName = exports.overrideFetchImplementation = exports.RunTree = exports.Client = void 0;
|
|
4
4
|
var client_js_1 = require("./client.cjs");
|
|
5
5
|
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_js_1.Client; } });
|
|
6
6
|
var run_trees_js_1 = require("./run_trees.cjs");
|
|
@@ -12,5 +12,7 @@ Object.defineProperty(exports, "getDefaultProjectName", { enumerable: true, get:
|
|
|
12
12
|
var uuid_js_1 = require("./uuid.cjs");
|
|
13
13
|
Object.defineProperty(exports, "uuid7", { enumerable: true, get: function () { return uuid_js_1.uuid7; } });
|
|
14
14
|
Object.defineProperty(exports, "uuid7FromTime", { enumerable: true, get: function () { return uuid_js_1.uuid7FromTime; } });
|
|
15
|
+
var prompts_cache_js_1 = require("./utils/prompts_cache.cjs");
|
|
16
|
+
Object.defineProperty(exports, "Cache", { enumerable: true, get: function () { return prompts_cache_js_1.Cache; } });
|
|
15
17
|
// Update using yarn bump-version
|
|
16
|
-
exports.__version__ = "0.4.
|
|
18
|
+
exports.__version__ = "0.4.5";
|
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
|
4
4
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
5
5
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
6
6
|
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
7
|
-
export
|
|
7
|
+
export { Cache, type CacheConfig, type CacheMetrics, } from "./utils/prompts_cache.js";
|
|
8
|
+
export declare const __version__ = "0.4.5";
|
package/dist/index.js
CHANGED
|
@@ -3,5 +3,6 @@ export { RunTree } from "./run_trees.js";
|
|
|
3
3
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
4
4
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
5
5
|
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
6
|
+
export { Cache, } from "./utils/prompts_cache.js";
|
|
6
7
|
// Update using yarn bump-version
|
|
7
|
-
export const __version__ = "0.4.
|
|
8
|
+
export const __version__ = "0.4.5";
|
package/dist/run_trees.cjs
CHANGED
|
@@ -616,15 +616,14 @@ class RunTree {
|
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
}
|
|
619
|
-
// Remap IDs for the replica using
|
|
620
|
-
// This ensures consistency across runs in the same replica
|
|
621
|
-
// preserving UUID7 properties (time-ordering, monotonicity)
|
|
619
|
+
// Remap IDs for the replica using uuid5 (deterministic)
|
|
620
|
+
// This ensures consistency across runs in the same replica
|
|
622
621
|
const oldId = baseRun.id;
|
|
623
|
-
const newId = (0,
|
|
622
|
+
const newId = (0, uuid_1.v5)(`${oldId}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
624
623
|
// Remap trace_id
|
|
625
624
|
let newTraceId;
|
|
626
625
|
if (baseRun.trace_id) {
|
|
627
|
-
newTraceId = (0,
|
|
626
|
+
newTraceId = (0, uuid_1.v5)(`${baseRun.trace_id}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
628
627
|
}
|
|
629
628
|
else {
|
|
630
629
|
newTraceId = newId;
|
|
@@ -632,7 +631,7 @@ class RunTree {
|
|
|
632
631
|
// Remap parent_run_id
|
|
633
632
|
let newParentId;
|
|
634
633
|
if (baseRun.parent_run_id) {
|
|
635
|
-
newParentId = (0,
|
|
634
|
+
newParentId = (0, uuid_1.v5)(`${baseRun.parent_run_id}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
636
635
|
}
|
|
637
636
|
// Remap dotted_order segments
|
|
638
637
|
let newDottedOrder;
|
|
@@ -641,7 +640,7 @@ class RunTree {
|
|
|
641
640
|
const remappedSegs = segs.map((seg) => {
|
|
642
641
|
// Extract the UUID from the segment (last TIMESTAMP_LENGTH characters)
|
|
643
642
|
const segId = seg.slice(-TIMESTAMP_LENGTH);
|
|
644
|
-
const remappedId = (0,
|
|
643
|
+
const remappedId = (0, uuid_1.v5)(`${segId}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
645
644
|
// Replace the UUID part while keeping the timestamp prefix
|
|
646
645
|
return seg.slice(0, -TIMESTAMP_LENGTH) + remappedId;
|
|
647
646
|
});
|
package/dist/run_trees.js
CHANGED
|
@@ -7,7 +7,7 @@ import { getEnvironmentVariable, getRuntimeEnvironment, } from "./utils/env.js";
|
|
|
7
7
|
import { getDefaultProjectName } from "./utils/project.js";
|
|
8
8
|
import { getLangSmithEnvironmentVariable } from "./utils/env.js";
|
|
9
9
|
import { warnOnce } from "./utils/warn.js";
|
|
10
|
-
import { uuid7FromTime
|
|
10
|
+
import { uuid7FromTime } from "./utils/_uuid.js";
|
|
11
11
|
import { v5 as uuidv5 } from "uuid";
|
|
12
12
|
const TIMESTAMP_LENGTH = 36;
|
|
13
13
|
// DNS namespace for UUID v5 (same as Python's uuid.NAMESPACE_DNS)
|
|
@@ -610,15 +610,14 @@ export class RunTree {
|
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
}
|
|
613
|
-
// Remap IDs for the replica using
|
|
614
|
-
// This ensures consistency across runs in the same replica
|
|
615
|
-
// preserving UUID7 properties (time-ordering, monotonicity)
|
|
613
|
+
// Remap IDs for the replica using uuid5 (deterministic)
|
|
614
|
+
// This ensures consistency across runs in the same replica
|
|
616
615
|
const oldId = baseRun.id;
|
|
617
|
-
const newId =
|
|
616
|
+
const newId = uuidv5(`${oldId}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
618
617
|
// Remap trace_id
|
|
619
618
|
let newTraceId;
|
|
620
619
|
if (baseRun.trace_id) {
|
|
621
|
-
newTraceId =
|
|
620
|
+
newTraceId = uuidv5(`${baseRun.trace_id}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
622
621
|
}
|
|
623
622
|
else {
|
|
624
623
|
newTraceId = newId;
|
|
@@ -626,7 +625,7 @@ export class RunTree {
|
|
|
626
625
|
// Remap parent_run_id
|
|
627
626
|
let newParentId;
|
|
628
627
|
if (baseRun.parent_run_id) {
|
|
629
|
-
newParentId =
|
|
628
|
+
newParentId = uuidv5(`${baseRun.parent_run_id}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
630
629
|
}
|
|
631
630
|
// Remap dotted_order segments
|
|
632
631
|
let newDottedOrder;
|
|
@@ -635,7 +634,7 @@ export class RunTree {
|
|
|
635
634
|
const remappedSegs = segs.map((seg) => {
|
|
636
635
|
// Extract the UUID from the segment (last TIMESTAMP_LENGTH characters)
|
|
637
636
|
const segId = seg.slice(-TIMESTAMP_LENGTH);
|
|
638
|
-
const remappedId =
|
|
637
|
+
const remappedId = uuidv5(`${segId}:${projectName}`, UUID_NAMESPACE_DNS);
|
|
639
638
|
// Replace the UUID part while keeping the timestamp prefix
|
|
640
639
|
return seg.slice(0, -TIMESTAMP_LENGTH) + remappedId;
|
|
641
640
|
});
|
package/dist/utils/_uuid.cjs
CHANGED
|
@@ -4,10 +4,8 @@ exports.assertUuid = assertUuid;
|
|
|
4
4
|
exports.uuid7FromTime = uuid7FromTime;
|
|
5
5
|
exports.getUuidVersion = getUuidVersion;
|
|
6
6
|
exports.warnIfNotUuidV7 = warnIfNotUuidV7;
|
|
7
|
-
exports.uuid7Deterministic = uuid7Deterministic;
|
|
8
7
|
// Relaxed UUID validation regex (allows any valid UUID format including nil UUIDs)
|
|
9
8
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10
|
-
const crypto_1 = require("crypto");
|
|
11
9
|
const uuid_1 = require("uuid");
|
|
12
10
|
const warn_js_1 = require("./warn.cjs");
|
|
13
11
|
let UUID7_WARNING_EMITTED = false;
|
|
@@ -66,88 +64,3 @@ function warnIfNotUuidV7(uuidStr, _idType) {
|
|
|
66
64
|
`Future versions will require UUID v7.`);
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Convert a UUID string to its 16-byte representation.
|
|
71
|
-
* @param uuidStr - The UUID string (with or without dashes)
|
|
72
|
-
* @returns A Buffer containing the 16 bytes of the UUID
|
|
73
|
-
*/
|
|
74
|
-
function uuidToBytes(uuidStr) {
|
|
75
|
-
const hex = uuidStr.replace(/-/g, "");
|
|
76
|
-
return Buffer.from(hex, "hex");
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Convert 16 bytes to a UUID string.
|
|
80
|
-
* @param bytes - A Buffer containing 16 bytes
|
|
81
|
-
* @returns A UUID string in standard format
|
|
82
|
-
*/
|
|
83
|
-
function bytesToUuid(bytes) {
|
|
84
|
-
const hex = bytes.toString("hex");
|
|
85
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Generate a deterministic UUID v7 derived from an original UUID and a key.
|
|
89
|
-
*
|
|
90
|
-
* This function creates a new UUID that:
|
|
91
|
-
* - Preserves the timestamp from the original UUID if it's UUID v7
|
|
92
|
-
* - Uses current time if the original is not UUID v7
|
|
93
|
-
* - Uses deterministic "random" bits derived from hashing the original + key
|
|
94
|
-
* - Is valid UUID v7 format
|
|
95
|
-
*
|
|
96
|
-
* This is used for creating replica IDs that maintain time-ordering properties
|
|
97
|
-
* while being deterministic across distributed systems.
|
|
98
|
-
*
|
|
99
|
-
* @param originalId - The source UUID string (ideally UUID v7 to preserve timestamp)
|
|
100
|
-
* @param key - A string key used for deterministic derivation (e.g., project name)
|
|
101
|
-
* @returns A new UUID v7 string with preserved timestamp (if original is v7) and
|
|
102
|
-
* deterministic random bits
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```typescript
|
|
106
|
-
* const original = uuidv7();
|
|
107
|
-
* const replicaId = uuid7Deterministic(original, "replica-project");
|
|
108
|
-
* // Same inputs always produce same output
|
|
109
|
-
* assert(uuid7Deterministic(original, "replica-project") === replicaId);
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
|
-
function uuid7Deterministic(originalId, key) {
|
|
113
|
-
// Generate deterministic bytes from hash of original + key
|
|
114
|
-
const hashInput = `${originalId}:${key}`;
|
|
115
|
-
const h = (0, crypto_1.createHash)("sha256").update(hashInput).digest();
|
|
116
|
-
// Build new UUID7:
|
|
117
|
-
// UUID7 structure (RFC 9562):
|
|
118
|
-
// [0-5] 48 bits: unix_ts_ms (timestamp in milliseconds)
|
|
119
|
-
// [6] 4 bits: version (0111 = 7) + 4 bits rand_a
|
|
120
|
-
// [7] 8 bits: rand_a (continued)
|
|
121
|
-
// [8] 2 bits: variant (10) + 6 bits rand_b
|
|
122
|
-
// [9-15] 56 bits: rand_b (continued)
|
|
123
|
-
const b = Buffer.alloc(16);
|
|
124
|
-
// Check if original is UUID v7 - if so, preserve its timestamp
|
|
125
|
-
// If not, use current time to ensure the derived UUID has a valid timestamp
|
|
126
|
-
const version = getUuidVersion(originalId);
|
|
127
|
-
if (version === 7) {
|
|
128
|
-
// Preserve timestamp from original UUID7 (bytes 0-5)
|
|
129
|
-
const originalBytes = uuidToBytes(originalId);
|
|
130
|
-
originalBytes.copy(b, 0, 0, 6);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
// Generate fresh timestamp for non-UUID7 inputs
|
|
134
|
-
// This matches the uuid npm package's v7 implementation:
|
|
135
|
-
// https://github.com/uuidjs/uuid/blob/main/src/v7.ts
|
|
136
|
-
const msecs = Date.now();
|
|
137
|
-
b[0] = (msecs / 0x10000000000) & 0xff;
|
|
138
|
-
b[1] = (msecs / 0x100000000) & 0xff;
|
|
139
|
-
b[2] = (msecs / 0x1000000) & 0xff;
|
|
140
|
-
b[3] = (msecs / 0x10000) & 0xff;
|
|
141
|
-
b[4] = (msecs / 0x100) & 0xff;
|
|
142
|
-
b[5] = msecs & 0xff;
|
|
143
|
-
}
|
|
144
|
-
// Set version 7 (0111) in high nibble + 4 bits from hash
|
|
145
|
-
b[6] = 0x70 | (h[0] & 0x0f);
|
|
146
|
-
// rand_a continued (8 bits from hash)
|
|
147
|
-
b[7] = h[1];
|
|
148
|
-
// Set variant (10) in high 2 bits + 6 bits from hash
|
|
149
|
-
b[8] = 0x80 | (h[2] & 0x3f);
|
|
150
|
-
// rand_b (56 bits = 7 bytes from hash)
|
|
151
|
-
h.copy(b, 9, 3, 10);
|
|
152
|
-
return bytesToUuid(b);
|
|
153
|
-
}
|
package/dist/utils/_uuid.d.ts
CHANGED
|
@@ -19,29 +19,3 @@ export declare function getUuidVersion(uuidStr: string): number | null;
|
|
|
19
19
|
* @param idType - The type of ID (e.g., "run_id", "trace_id") for the warning message
|
|
20
20
|
*/
|
|
21
21
|
export declare function warnIfNotUuidV7(uuidStr: string, _idType: string): void;
|
|
22
|
-
/**
|
|
23
|
-
* Generate a deterministic UUID v7 derived from an original UUID and a key.
|
|
24
|
-
*
|
|
25
|
-
* This function creates a new UUID that:
|
|
26
|
-
* - Preserves the timestamp from the original UUID if it's UUID v7
|
|
27
|
-
* - Uses current time if the original is not UUID v7
|
|
28
|
-
* - Uses deterministic "random" bits derived from hashing the original + key
|
|
29
|
-
* - Is valid UUID v7 format
|
|
30
|
-
*
|
|
31
|
-
* This is used for creating replica IDs that maintain time-ordering properties
|
|
32
|
-
* while being deterministic across distributed systems.
|
|
33
|
-
*
|
|
34
|
-
* @param originalId - The source UUID string (ideally UUID v7 to preserve timestamp)
|
|
35
|
-
* @param key - A string key used for deterministic derivation (e.g., project name)
|
|
36
|
-
* @returns A new UUID v7 string with preserved timestamp (if original is v7) and
|
|
37
|
-
* deterministic random bits
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```typescript
|
|
41
|
-
* const original = uuidv7();
|
|
42
|
-
* const replicaId = uuid7Deterministic(original, "replica-project");
|
|
43
|
-
* // Same inputs always produce same output
|
|
44
|
-
* assert(uuid7Deterministic(original, "replica-project") === replicaId);
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export declare function uuid7Deterministic(originalId: string, key: string): string;
|
package/dist/utils/_uuid.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Relaxed UUID validation regex (allows any valid UUID format including nil UUIDs)
|
|
2
2
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3
|
-
import { createHash } from "crypto";
|
|
4
3
|
import { v7 as uuidv7 } from "uuid";
|
|
5
4
|
import { warnOnce } from "./warn.js";
|
|
6
5
|
let UUID7_WARNING_EMITTED = false;
|
|
@@ -59,88 +58,3 @@ export function warnIfNotUuidV7(uuidStr, _idType) {
|
|
|
59
58
|
`Future versions will require UUID v7.`);
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Convert a UUID string to its 16-byte representation.
|
|
64
|
-
* @param uuidStr - The UUID string (with or without dashes)
|
|
65
|
-
* @returns A Buffer containing the 16 bytes of the UUID
|
|
66
|
-
*/
|
|
67
|
-
function uuidToBytes(uuidStr) {
|
|
68
|
-
const hex = uuidStr.replace(/-/g, "");
|
|
69
|
-
return Buffer.from(hex, "hex");
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Convert 16 bytes to a UUID string.
|
|
73
|
-
* @param bytes - A Buffer containing 16 bytes
|
|
74
|
-
* @returns A UUID string in standard format
|
|
75
|
-
*/
|
|
76
|
-
function bytesToUuid(bytes) {
|
|
77
|
-
const hex = bytes.toString("hex");
|
|
78
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Generate a deterministic UUID v7 derived from an original UUID and a key.
|
|
82
|
-
*
|
|
83
|
-
* This function creates a new UUID that:
|
|
84
|
-
* - Preserves the timestamp from the original UUID if it's UUID v7
|
|
85
|
-
* - Uses current time if the original is not UUID v7
|
|
86
|
-
* - Uses deterministic "random" bits derived from hashing the original + key
|
|
87
|
-
* - Is valid UUID v7 format
|
|
88
|
-
*
|
|
89
|
-
* This is used for creating replica IDs that maintain time-ordering properties
|
|
90
|
-
* while being deterministic across distributed systems.
|
|
91
|
-
*
|
|
92
|
-
* @param originalId - The source UUID string (ideally UUID v7 to preserve timestamp)
|
|
93
|
-
* @param key - A string key used for deterministic derivation (e.g., project name)
|
|
94
|
-
* @returns A new UUID v7 string with preserved timestamp (if original is v7) and
|
|
95
|
-
* deterministic random bits
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* const original = uuidv7();
|
|
100
|
-
* const replicaId = uuid7Deterministic(original, "replica-project");
|
|
101
|
-
* // Same inputs always produce same output
|
|
102
|
-
* assert(uuid7Deterministic(original, "replica-project") === replicaId);
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
export function uuid7Deterministic(originalId, key) {
|
|
106
|
-
// Generate deterministic bytes from hash of original + key
|
|
107
|
-
const hashInput = `${originalId}:${key}`;
|
|
108
|
-
const h = createHash("sha256").update(hashInput).digest();
|
|
109
|
-
// Build new UUID7:
|
|
110
|
-
// UUID7 structure (RFC 9562):
|
|
111
|
-
// [0-5] 48 bits: unix_ts_ms (timestamp in milliseconds)
|
|
112
|
-
// [6] 4 bits: version (0111 = 7) + 4 bits rand_a
|
|
113
|
-
// [7] 8 bits: rand_a (continued)
|
|
114
|
-
// [8] 2 bits: variant (10) + 6 bits rand_b
|
|
115
|
-
// [9-15] 56 bits: rand_b (continued)
|
|
116
|
-
const b = Buffer.alloc(16);
|
|
117
|
-
// Check if original is UUID v7 - if so, preserve its timestamp
|
|
118
|
-
// If not, use current time to ensure the derived UUID has a valid timestamp
|
|
119
|
-
const version = getUuidVersion(originalId);
|
|
120
|
-
if (version === 7) {
|
|
121
|
-
// Preserve timestamp from original UUID7 (bytes 0-5)
|
|
122
|
-
const originalBytes = uuidToBytes(originalId);
|
|
123
|
-
originalBytes.copy(b, 0, 0, 6);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
// Generate fresh timestamp for non-UUID7 inputs
|
|
127
|
-
// This matches the uuid npm package's v7 implementation:
|
|
128
|
-
// https://github.com/uuidjs/uuid/blob/main/src/v7.ts
|
|
129
|
-
const msecs = Date.now();
|
|
130
|
-
b[0] = (msecs / 0x10000000000) & 0xff;
|
|
131
|
-
b[1] = (msecs / 0x100000000) & 0xff;
|
|
132
|
-
b[2] = (msecs / 0x1000000) & 0xff;
|
|
133
|
-
b[3] = (msecs / 0x10000) & 0xff;
|
|
134
|
-
b[4] = (msecs / 0x100) & 0xff;
|
|
135
|
-
b[5] = msecs & 0xff;
|
|
136
|
-
}
|
|
137
|
-
// Set version 7 (0111) in high nibble + 4 bits from hash
|
|
138
|
-
b[6] = 0x70 | (h[0] & 0x0f);
|
|
139
|
-
// rand_a continued (8 bits from hash)
|
|
140
|
-
b[7] = h[1];
|
|
141
|
-
// Set variant (10) in high 2 bits + 6 bits from hash
|
|
142
|
-
b[8] = 0x80 | (h[2] & 0x3f);
|
|
143
|
-
// rand_b (56 bits = 7 bytes from hash)
|
|
144
|
-
h.copy(b, 9, 3, 10);
|
|
145
|
-
return bytesToUuid(b);
|
|
146
|
-
}
|
|
@@ -4,44 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Provides an LRU cache with background refresh for prompt caching.
|
|
6
6
|
* Uses stale-while-revalidate pattern for optimal performance.
|
|
7
|
+
*
|
|
8
|
+
* Works in all environments. File operations (dump/load) use helpers
|
|
9
|
+
* that are swapped for browser builds via package.json browser field.
|
|
7
10
|
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.
|
|
43
|
-
const
|
|
44
|
-
const path = __importStar(require("node:path"));
|
|
12
|
+
exports.Cache = void 0;
|
|
13
|
+
const prompts_cache_fs_js_1 = require("./prompts_cache_fs.cjs");
|
|
45
14
|
/**
|
|
46
15
|
* Check if a cache entry is stale based on TTL.
|
|
47
16
|
*/
|
|
@@ -63,7 +32,7 @@ function isStale(entry, ttlSeconds) {
|
|
|
63
32
|
*
|
|
64
33
|
* @example
|
|
65
34
|
* ```typescript
|
|
66
|
-
* const cache = new
|
|
35
|
+
* const cache = new Cache({
|
|
67
36
|
* maxSize: 100,
|
|
68
37
|
* ttlSeconds: 3600,
|
|
69
38
|
* fetchFunc: async (key) => client.pullPromptCommit(key),
|
|
@@ -77,7 +46,7 @@ function isStale(entry, ttlSeconds) {
|
|
|
77
46
|
* cache.stop();
|
|
78
47
|
* ```
|
|
79
48
|
*/
|
|
80
|
-
class
|
|
49
|
+
class Cache {
|
|
81
50
|
constructor(config = {}) {
|
|
82
51
|
Object.defineProperty(this, "cache", {
|
|
83
52
|
enumerable: true,
|
|
@@ -235,28 +204,11 @@ class PromptCache {
|
|
|
235
204
|
* Dump cache contents to a JSON file for offline use.
|
|
236
205
|
*/
|
|
237
206
|
dump(filePath) {
|
|
238
|
-
const dir = path.dirname(filePath);
|
|
239
|
-
if (!fs.existsSync(dir)) {
|
|
240
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
241
|
-
}
|
|
242
207
|
const entries = {};
|
|
243
208
|
for (const [key, entry] of this.cache.entries()) {
|
|
244
209
|
entries[key] = entry.value;
|
|
245
210
|
}
|
|
246
|
-
|
|
247
|
-
// Atomic write: write to temp file then rename
|
|
248
|
-
const tempPath = `${filePath}.tmp`;
|
|
249
|
-
try {
|
|
250
|
-
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
251
|
-
fs.renameSync(tempPath, filePath);
|
|
252
|
-
}
|
|
253
|
-
catch (e) {
|
|
254
|
-
// Clean up temp file on failure
|
|
255
|
-
if (fs.existsSync(tempPath)) {
|
|
256
|
-
fs.unlinkSync(tempPath);
|
|
257
|
-
}
|
|
258
|
-
throw e;
|
|
259
|
-
}
|
|
211
|
+
(0, prompts_cache_fs_js_1.dumpCache)(filePath, entries);
|
|
260
212
|
}
|
|
261
213
|
/**
|
|
262
214
|
* Load cache contents from a JSON file.
|
|
@@ -266,18 +218,10 @@ class PromptCache {
|
|
|
266
218
|
* @returns Number of entries loaded.
|
|
267
219
|
*/
|
|
268
220
|
load(filePath) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
let data;
|
|
273
|
-
try {
|
|
274
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
275
|
-
data = JSON.parse(content);
|
|
276
|
-
}
|
|
277
|
-
catch {
|
|
221
|
+
const entries = (0, prompts_cache_fs_js_1.loadCache)(filePath);
|
|
222
|
+
if (!entries) {
|
|
278
223
|
return 0;
|
|
279
224
|
}
|
|
280
|
-
const entries = data.entries ?? {};
|
|
281
225
|
let loaded = 0;
|
|
282
226
|
const now = Date.now();
|
|
283
227
|
for (const [key, value] of Object.entries(entries)) {
|
|
@@ -285,7 +229,7 @@ class PromptCache {
|
|
|
285
229
|
break;
|
|
286
230
|
}
|
|
287
231
|
const entry = {
|
|
288
|
-
value,
|
|
232
|
+
value: value,
|
|
289
233
|
createdAt: now, // Fresh TTL from load time
|
|
290
234
|
};
|
|
291
235
|
this.cache.set(key, entry);
|
|
@@ -345,4 +289,4 @@ class PromptCache {
|
|
|
345
289
|
}
|
|
346
290
|
}
|
|
347
291
|
}
|
|
348
|
-
exports.
|
|
292
|
+
exports.Cache = Cache;
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides an LRU cache with background refresh for prompt caching.
|
|
5
5
|
* Uses stale-while-revalidate pattern for optimal performance.
|
|
6
|
+
*
|
|
7
|
+
* Works in all environments. File operations (dump/load) use helpers
|
|
8
|
+
* that are swapped for browser builds via package.json browser field.
|
|
6
9
|
*/
|
|
7
10
|
import type { PromptCommit } from "../schemas.js";
|
|
8
11
|
/**
|
|
@@ -22,9 +25,9 @@ export interface CacheMetrics {
|
|
|
22
25
|
refreshErrors: number;
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
|
-
* Configuration options for
|
|
28
|
+
* Configuration options for Cache.
|
|
26
29
|
*/
|
|
27
|
-
export interface
|
|
30
|
+
export interface CacheConfig {
|
|
28
31
|
/** Maximum entries in cache (LRU eviction when exceeded). Default: 100 */
|
|
29
32
|
maxSize?: number;
|
|
30
33
|
/** Time in seconds before entry is stale. null = infinite TTL. Default: 3600 */
|
|
@@ -45,7 +48,7 @@ export interface PromptCacheConfig {
|
|
|
45
48
|
*
|
|
46
49
|
* @example
|
|
47
50
|
* ```typescript
|
|
48
|
-
* const cache = new
|
|
51
|
+
* const cache = new Cache({
|
|
49
52
|
* maxSize: 100,
|
|
50
53
|
* ttlSeconds: 3600,
|
|
51
54
|
* fetchFunc: async (key) => client.pullPromptCommit(key),
|
|
@@ -59,7 +62,7 @@ export interface PromptCacheConfig {
|
|
|
59
62
|
* cache.stop();
|
|
60
63
|
* ```
|
|
61
64
|
*/
|
|
62
|
-
export declare class
|
|
65
|
+
export declare class Cache {
|
|
63
66
|
private cache;
|
|
64
67
|
private maxSize;
|
|
65
68
|
private ttlSeconds;
|
|
@@ -67,7 +70,7 @@ export declare class PromptCache {
|
|
|
67
70
|
private fetchFunc?;
|
|
68
71
|
private refreshTimer?;
|
|
69
72
|
private _metrics;
|
|
70
|
-
constructor(config?:
|
|
73
|
+
constructor(config?: CacheConfig);
|
|
71
74
|
/**
|
|
72
75
|
* Get cache performance metrics.
|
|
73
76
|
*/
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides an LRU cache with background refresh for prompt caching.
|
|
5
5
|
* Uses stale-while-revalidate pattern for optimal performance.
|
|
6
|
+
*
|
|
7
|
+
* Works in all environments. File operations (dump/load) use helpers
|
|
8
|
+
* that are swapped for browser builds via package.json browser field.
|
|
6
9
|
*/
|
|
7
|
-
import
|
|
8
|
-
import * as path from "node:path";
|
|
10
|
+
import { dumpCache, loadCache } from "./prompts_cache_fs.js";
|
|
9
11
|
/**
|
|
10
12
|
* Check if a cache entry is stale based on TTL.
|
|
11
13
|
*/
|
|
@@ -27,7 +29,7 @@ function isStale(entry, ttlSeconds) {
|
|
|
27
29
|
*
|
|
28
30
|
* @example
|
|
29
31
|
* ```typescript
|
|
30
|
-
* const cache = new
|
|
32
|
+
* const cache = new Cache({
|
|
31
33
|
* maxSize: 100,
|
|
32
34
|
* ttlSeconds: 3600,
|
|
33
35
|
* fetchFunc: async (key) => client.pullPromptCommit(key),
|
|
@@ -41,7 +43,7 @@ function isStale(entry, ttlSeconds) {
|
|
|
41
43
|
* cache.stop();
|
|
42
44
|
* ```
|
|
43
45
|
*/
|
|
44
|
-
export class
|
|
46
|
+
export class Cache {
|
|
45
47
|
constructor(config = {}) {
|
|
46
48
|
Object.defineProperty(this, "cache", {
|
|
47
49
|
enumerable: true,
|
|
@@ -199,28 +201,11 @@ export class PromptCache {
|
|
|
199
201
|
* Dump cache contents to a JSON file for offline use.
|
|
200
202
|
*/
|
|
201
203
|
dump(filePath) {
|
|
202
|
-
const dir = path.dirname(filePath);
|
|
203
|
-
if (!fs.existsSync(dir)) {
|
|
204
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
205
|
-
}
|
|
206
204
|
const entries = {};
|
|
207
205
|
for (const [key, entry] of this.cache.entries()) {
|
|
208
206
|
entries[key] = entry.value;
|
|
209
207
|
}
|
|
210
|
-
|
|
211
|
-
// Atomic write: write to temp file then rename
|
|
212
|
-
const tempPath = `${filePath}.tmp`;
|
|
213
|
-
try {
|
|
214
|
-
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
215
|
-
fs.renameSync(tempPath, filePath);
|
|
216
|
-
}
|
|
217
|
-
catch (e) {
|
|
218
|
-
// Clean up temp file on failure
|
|
219
|
-
if (fs.existsSync(tempPath)) {
|
|
220
|
-
fs.unlinkSync(tempPath);
|
|
221
|
-
}
|
|
222
|
-
throw e;
|
|
223
|
-
}
|
|
208
|
+
dumpCache(filePath, entries);
|
|
224
209
|
}
|
|
225
210
|
/**
|
|
226
211
|
* Load cache contents from a JSON file.
|
|
@@ -230,18 +215,10 @@ export class PromptCache {
|
|
|
230
215
|
* @returns Number of entries loaded.
|
|
231
216
|
*/
|
|
232
217
|
load(filePath) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
let data;
|
|
237
|
-
try {
|
|
238
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
239
|
-
data = JSON.parse(content);
|
|
240
|
-
}
|
|
241
|
-
catch {
|
|
218
|
+
const entries = loadCache(filePath);
|
|
219
|
+
if (!entries) {
|
|
242
220
|
return 0;
|
|
243
221
|
}
|
|
244
|
-
const entries = data.entries ?? {};
|
|
245
222
|
let loaded = 0;
|
|
246
223
|
const now = Date.now();
|
|
247
224
|
for (const [key, value] of Object.entries(entries)) {
|
|
@@ -249,7 +226,7 @@ export class PromptCache {
|
|
|
249
226
|
break;
|
|
250
227
|
}
|
|
251
228
|
const entry = {
|
|
252
|
-
value,
|
|
229
|
+
value: value,
|
|
253
230
|
createdAt: now, // Fresh TTL from load time
|
|
254
231
|
};
|
|
255
232
|
this.cache.set(key, entry);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* File system operations for prompt cache (Browser version).
|
|
4
|
+
*
|
|
5
|
+
* This stub is used in browser builds via the package.json browser field.
|
|
6
|
+
* File operations are not supported in browser environments.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.dumpCache = dumpCache;
|
|
10
|
+
exports.loadCache = loadCache;
|
|
11
|
+
/**
|
|
12
|
+
* Dump cache entries to a JSON file.
|
|
13
|
+
* @throws Error - Always throws in browser environments.
|
|
14
|
+
*/
|
|
15
|
+
function dumpCache(_filePath, _entries) {
|
|
16
|
+
throw new Error("dump() is not supported in browser environments.");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load cache entries from a JSON file.
|
|
20
|
+
* @throws Error - Always throws in browser environments.
|
|
21
|
+
*/
|
|
22
|
+
function loadCache(_filePath) {
|
|
23
|
+
throw new Error("load() is not supported in browser environments.");
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system operations for prompt cache (Browser version).
|
|
3
|
+
*
|
|
4
|
+
* This stub is used in browser builds via the package.json browser field.
|
|
5
|
+
* File operations are not supported in browser environments.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Dump cache entries to a JSON file.
|
|
9
|
+
* @throws Error - Always throws in browser environments.
|
|
10
|
+
*/
|
|
11
|
+
export declare function dumpCache(_filePath: string, _entries: Record<string, unknown>): void;
|
|
12
|
+
/**
|
|
13
|
+
* Load cache entries from a JSON file.
|
|
14
|
+
* @throws Error - Always throws in browser environments.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadCache(_filePath: string): Record<string, unknown> | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system operations for prompt cache (Browser version).
|
|
3
|
+
*
|
|
4
|
+
* This stub is used in browser builds via the package.json browser field.
|
|
5
|
+
* File operations are not supported in browser environments.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Dump cache entries to a JSON file.
|
|
9
|
+
* @throws Error - Always throws in browser environments.
|
|
10
|
+
*/
|
|
11
|
+
export function dumpCache(_filePath, _entries) {
|
|
12
|
+
throw new Error("dump() is not supported in browser environments.");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load cache entries from a JSON file.
|
|
16
|
+
* @throws Error - Always throws in browser environments.
|
|
17
|
+
*/
|
|
18
|
+
export function loadCache(_filePath) {
|
|
19
|
+
throw new Error("load() is not supported in browser environments.");
|
|
20
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* File system operations for prompt cache (Node.js version).
|
|
4
|
+
*
|
|
5
|
+
* This file is swapped with prompts_cache_fs.browser.ts for browser builds
|
|
6
|
+
* via the package.json browser field.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.dumpCache = dumpCache;
|
|
43
|
+
exports.loadCache = loadCache;
|
|
44
|
+
const fs = __importStar(require("node:fs"));
|
|
45
|
+
const path = __importStar(require("node:path"));
|
|
46
|
+
/**
|
|
47
|
+
* Dump cache entries to a JSON file.
|
|
48
|
+
*/
|
|
49
|
+
function dumpCache(filePath, entries) {
|
|
50
|
+
const dir = path.dirname(filePath);
|
|
51
|
+
if (!fs.existsSync(dir)) {
|
|
52
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
const data = { entries };
|
|
55
|
+
// Atomic write: write to temp file then rename
|
|
56
|
+
const tempPath = `${filePath}.tmp`;
|
|
57
|
+
try {
|
|
58
|
+
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
59
|
+
fs.renameSync(tempPath, filePath);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
// Clean up temp file on failure
|
|
63
|
+
if (fs.existsSync(tempPath)) {
|
|
64
|
+
fs.unlinkSync(tempPath);
|
|
65
|
+
}
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Load cache entries from a JSON file.
|
|
71
|
+
*
|
|
72
|
+
* @returns The entries object, or null if file doesn't exist or is invalid.
|
|
73
|
+
*/
|
|
74
|
+
function loadCache(filePath) {
|
|
75
|
+
if (!fs.existsSync(filePath)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
80
|
+
const data = JSON.parse(content);
|
|
81
|
+
return data.entries ?? null;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system operations for prompt cache (Node.js version).
|
|
3
|
+
*
|
|
4
|
+
* This file is swapped with prompts_cache_fs.browser.ts for browser builds
|
|
5
|
+
* via the package.json browser field.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Dump cache entries to a JSON file.
|
|
9
|
+
*/
|
|
10
|
+
export declare function dumpCache(filePath: string, entries: Record<string, unknown>): void;
|
|
11
|
+
/**
|
|
12
|
+
* Load cache entries from a JSON file.
|
|
13
|
+
*
|
|
14
|
+
* @returns The entries object, or null if file doesn't exist or is invalid.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadCache(filePath: string): Record<string, unknown> | null;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system operations for prompt cache (Node.js version).
|
|
3
|
+
*
|
|
4
|
+
* This file is swapped with prompts_cache_fs.browser.ts for browser builds
|
|
5
|
+
* via the package.json browser field.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
/**
|
|
10
|
+
* Dump cache entries to a JSON file.
|
|
11
|
+
*/
|
|
12
|
+
export function dumpCache(filePath, entries) {
|
|
13
|
+
const dir = path.dirname(filePath);
|
|
14
|
+
if (!fs.existsSync(dir)) {
|
|
15
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
const data = { entries };
|
|
18
|
+
// Atomic write: write to temp file then rename
|
|
19
|
+
const tempPath = `${filePath}.tmp`;
|
|
20
|
+
try {
|
|
21
|
+
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
22
|
+
fs.renameSync(tempPath, filePath);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
// Clean up temp file on failure
|
|
26
|
+
if (fs.existsSync(tempPath)) {
|
|
27
|
+
fs.unlinkSync(tempPath);
|
|
28
|
+
}
|
|
29
|
+
throw e;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Load cache entries from a JSON file.
|
|
34
|
+
*
|
|
35
|
+
* @returns The entries object, or null if file doesn't exist or is invalid.
|
|
36
|
+
*/
|
|
37
|
+
export function loadCache(filePath) {
|
|
38
|
+
if (!fs.existsSync(filePath)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
43
|
+
const data = JSON.parse(content);
|
|
44
|
+
return data.entries ?? null;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
|
|
5
5
|
"packageManager": "yarn@1.22.19",
|
|
6
6
|
"files": [
|
|
@@ -401,5 +401,8 @@
|
|
|
401
401
|
"require": "./experimental/vercel.cjs"
|
|
402
402
|
},
|
|
403
403
|
"./package.json": "./package.json"
|
|
404
|
+
},
|
|
405
|
+
"browser": {
|
|
406
|
+
"./dist/utils/prompts_cache_fs.js": "./dist/utils/prompts_cache_fs.browser.js"
|
|
404
407
|
}
|
|
405
408
|
}
|