langsmith 0.5.21 → 0.5.23
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 +327 -10
- package/dist/client.d.ts +90 -1
- package/dist/client.js +330 -13
- package/dist/evaluation/_runner.cjs +1 -4
- package/dist/evaluation/_runner.js +1 -4
- package/dist/experimental/sandbox/client.cjs +102 -427
- package/dist/experimental/sandbox/client.d.ts +68 -159
- package/dist/experimental/sandbox/client.js +104 -429
- 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 +3 -11
- package/dist/experimental/sandbox/sandbox.d.ts +3 -5
- package/dist/experimental/sandbox/sandbox.js +3 -11
- package/dist/experimental/sandbox/types.d.ts +32 -149
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas.d.ts +54 -0
- package/dist/utils/error.cjs +7 -0
- package/dist/utils/error.d.ts +1 -0
- package/dist/utils/error.js +6 -0
- package/dist/utils/fast-safe-stringify/index.cjs +228 -0
- package/dist/utils/fast-safe-stringify/index.d.ts +33 -0
- package/dist/utils/fast-safe-stringify/index.js +227 -0
- package/dist/utils/prompts.cjs +7 -2
- package/dist/utils/prompts.d.ts +6 -1
- package/dist/utils/prompts.js +6 -1
- 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/package.json +22 -6
- 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
|
@@ -11,59 +11,6 @@ export interface ExecutionResult {
|
|
|
11
11
|
stderr: string;
|
|
12
12
|
exit_code: number;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Resource specification for a sandbox.
|
|
16
|
-
*/
|
|
17
|
-
export interface ResourceSpec {
|
|
18
|
-
cpu?: string;
|
|
19
|
-
memory?: string;
|
|
20
|
-
storage?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Specification for mounting a volume in a sandbox template.
|
|
24
|
-
*/
|
|
25
|
-
export interface VolumeMountSpec {
|
|
26
|
-
volume_name: string;
|
|
27
|
-
mount_path: string;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Represents a persistent volume.
|
|
31
|
-
*/
|
|
32
|
-
export interface Volume {
|
|
33
|
-
id?: string;
|
|
34
|
-
name: string;
|
|
35
|
-
size: string;
|
|
36
|
-
storage_class: string;
|
|
37
|
-
created_at?: string;
|
|
38
|
-
updated_at?: string;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Represents a SandboxTemplate.
|
|
42
|
-
*
|
|
43
|
-
* Templates define the image, resource limits, and volume mounts for sandboxes.
|
|
44
|
-
*/
|
|
45
|
-
export interface SandboxTemplate {
|
|
46
|
-
id?: string;
|
|
47
|
-
name: string;
|
|
48
|
-
image: string;
|
|
49
|
-
resources: ResourceSpec;
|
|
50
|
-
volume_mounts?: VolumeMountSpec[];
|
|
51
|
-
created_at?: string;
|
|
52
|
-
updated_at?: string;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Represents a Sandbox Pool for pre-provisioned sandboxes.
|
|
56
|
-
*
|
|
57
|
-
* Pools pre-provision sandboxes from a template for faster startup.
|
|
58
|
-
*/
|
|
59
|
-
export interface Pool {
|
|
60
|
-
id?: string;
|
|
61
|
-
name: string;
|
|
62
|
-
template_name: string;
|
|
63
|
-
replicas: number;
|
|
64
|
-
created_at?: string;
|
|
65
|
-
updated_at?: string;
|
|
66
|
-
}
|
|
67
14
|
/**
|
|
68
15
|
* Lightweight provisioning status for any async-created resource.
|
|
69
16
|
*/
|
|
@@ -101,7 +48,6 @@ export interface Snapshot {
|
|
|
101
48
|
export interface SandboxData {
|
|
102
49
|
id?: string;
|
|
103
50
|
name: string;
|
|
104
|
-
template_name?: string;
|
|
105
51
|
dataplane_url?: string;
|
|
106
52
|
status?: string;
|
|
107
53
|
status_message?: string;
|
|
@@ -297,10 +243,11 @@ export interface SandboxProxyConfig {
|
|
|
297
243
|
*/
|
|
298
244
|
export interface CreateSandboxOptions {
|
|
299
245
|
/**
|
|
300
|
-
* Snapshot
|
|
301
|
-
*
|
|
246
|
+
* Snapshot name to boot from. Mutually exclusive with the positional
|
|
247
|
+
* `snapshotId` argument on `createSandbox`; exactly one must be provided.
|
|
248
|
+
* Resolved server-side to a snapshot owned by the caller's tenant.
|
|
302
249
|
*/
|
|
303
|
-
|
|
250
|
+
snapshotName?: string;
|
|
304
251
|
/**
|
|
305
252
|
* Optional sandbox name (auto-generated if not provided).
|
|
306
253
|
*/
|
|
@@ -361,13 +308,39 @@ export interface CreateSnapshotOptions {
|
|
|
361
308
|
* Options for capturing a snapshot from a running sandbox.
|
|
362
309
|
*/
|
|
363
310
|
export interface CaptureSnapshotOptions {
|
|
364
|
-
/** Checkpoint timestamp to use. If omitted, creates a fresh checkpoint. */
|
|
365
|
-
checkpoint?: string;
|
|
366
311
|
/** Timeout in seconds when waiting for ready. Default: 60. */
|
|
367
312
|
timeout?: number;
|
|
368
313
|
/** AbortSignal for cancellation. */
|
|
369
314
|
signal?: AbortSignal;
|
|
370
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Options for listing snapshots. All fields are optional and independent.
|
|
318
|
+
*
|
|
319
|
+
* The backend always paginates: when `limit` is omitted the server applies
|
|
320
|
+
* a default page size (currently 50), so a single call will not necessarily
|
|
321
|
+
* return every snapshot visible to the caller's tenant.
|
|
322
|
+
*/
|
|
323
|
+
export interface ListSnapshotsOptions {
|
|
324
|
+
/**
|
|
325
|
+
* Case-insensitive substring filter applied server-side to snapshot
|
|
326
|
+
* names.
|
|
327
|
+
*/
|
|
328
|
+
nameContains?: string;
|
|
329
|
+
/**
|
|
330
|
+
* Maximum number of snapshots to return for a single request. Must be
|
|
331
|
+
* between 1 and 500 (inclusive); the server rejects values outside that
|
|
332
|
+
* range. Defaults to 50 server-side when omitted.
|
|
333
|
+
*/
|
|
334
|
+
limit?: number;
|
|
335
|
+
/**
|
|
336
|
+
* Number of snapshots to skip before returning results. Must be `>= 0`.
|
|
337
|
+
* Useful for paginating through large result sets in combination with
|
|
338
|
+
* `limit`.
|
|
339
|
+
*/
|
|
340
|
+
offset?: number;
|
|
341
|
+
/** AbortSignal for cancellation. */
|
|
342
|
+
signal?: AbortSignal;
|
|
343
|
+
}
|
|
371
344
|
/**
|
|
372
345
|
* Options for waiting for a snapshot to become ready.
|
|
373
346
|
*/
|
|
@@ -421,93 +394,3 @@ export interface WaitForSandboxOptions {
|
|
|
421
394
|
/** AbortSignal for cancellation. */
|
|
422
395
|
signal?: AbortSignal;
|
|
423
396
|
}
|
|
424
|
-
/**
|
|
425
|
-
* Options for creating a volume.
|
|
426
|
-
*/
|
|
427
|
-
export interface CreateVolumeOptions {
|
|
428
|
-
/**
|
|
429
|
-
* Storage size (e.g., "1Gi", "10Gi").
|
|
430
|
-
*/
|
|
431
|
-
size: string;
|
|
432
|
-
/**
|
|
433
|
-
* Timeout in seconds when waiting for volume to be ready. Default: 60.
|
|
434
|
-
*/
|
|
435
|
-
timeout?: number;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Options for creating a template.
|
|
439
|
-
*/
|
|
440
|
-
export interface CreateTemplateOptions {
|
|
441
|
-
/**
|
|
442
|
-
* Container image (e.g., "python:3.12-slim", "node:20-slim").
|
|
443
|
-
*/
|
|
444
|
-
image: string;
|
|
445
|
-
/**
|
|
446
|
-
* CPU limit (e.g., "500m", "1", "2"). Default: "500m".
|
|
447
|
-
*/
|
|
448
|
-
cpu?: string;
|
|
449
|
-
/**
|
|
450
|
-
* Memory limit (e.g., "256Mi", "1Gi"). Default: "512Mi".
|
|
451
|
-
*/
|
|
452
|
-
memory?: string;
|
|
453
|
-
/**
|
|
454
|
-
* Ephemeral storage limit (e.g., "1Gi"). Optional.
|
|
455
|
-
*/
|
|
456
|
-
storage?: string;
|
|
457
|
-
/**
|
|
458
|
-
* List of volumes to mount in the sandbox. Optional.
|
|
459
|
-
*/
|
|
460
|
-
volumeMounts?: VolumeMountSpec[];
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Options for updating a template.
|
|
464
|
-
*/
|
|
465
|
-
export interface UpdateTemplateOptions {
|
|
466
|
-
/**
|
|
467
|
-
* New display name (optional).
|
|
468
|
-
*/
|
|
469
|
-
newName?: string;
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Options for creating a pool.
|
|
473
|
-
*/
|
|
474
|
-
export interface CreatePoolOptions {
|
|
475
|
-
/**
|
|
476
|
-
* Name of the template to use for sandboxes in this pool.
|
|
477
|
-
*/
|
|
478
|
-
templateName: string;
|
|
479
|
-
/**
|
|
480
|
-
* Number of pre-warmed sandboxes to maintain (0-100).
|
|
481
|
-
*/
|
|
482
|
-
replicas: number;
|
|
483
|
-
/**
|
|
484
|
-
* Timeout in seconds when waiting for pool to be ready. Default: 30.
|
|
485
|
-
*/
|
|
486
|
-
timeout?: number;
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Options for updating a volume.
|
|
490
|
-
*/
|
|
491
|
-
export interface UpdateVolumeOptions {
|
|
492
|
-
/**
|
|
493
|
-
* New display name (optional).
|
|
494
|
-
*/
|
|
495
|
-
newName?: string;
|
|
496
|
-
/**
|
|
497
|
-
* New storage size (must be >= current size). Optional.
|
|
498
|
-
*/
|
|
499
|
-
size?: string;
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Options for updating a pool.
|
|
503
|
-
*/
|
|
504
|
-
export interface UpdatePoolOptions {
|
|
505
|
-
/**
|
|
506
|
-
* New display name (optional).
|
|
507
|
-
*/
|
|
508
|
-
newName?: string;
|
|
509
|
-
/**
|
|
510
|
-
* New number of replicas (0-100). Set to 0 to pause.
|
|
511
|
-
*/
|
|
512
|
-
replicas?: number;
|
|
513
|
-
}
|
package/dist/index.cjs
CHANGED
|
@@ -18,4 +18,4 @@ Object.defineProperty(exports, "PromptCache", { enumerable: true, get: function
|
|
|
18
18
|
Object.defineProperty(exports, "configureGlobalPromptCache", { enumerable: true, get: function () { return index_js_1.configureGlobalPromptCache; } });
|
|
19
19
|
Object.defineProperty(exports, "promptCacheSingleton", { enumerable: true, get: function () { return index_js_1.promptCacheSingleton; } });
|
|
20
20
|
// Update using pnpm bump-version
|
|
21
|
-
exports.__version__ = "0.5.
|
|
21
|
+
exports.__version__ = "0.5.23";
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,4 @@ export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
|
5
5
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
6
6
|
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
7
7
|
export { Cache, PromptCache, type CacheConfig, type CacheMetrics, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
8
|
-
export declare const __version__ = "0.5.
|
|
8
|
+
export declare const __version__ = "0.5.23";
|
package/dist/index.js
CHANGED
|
@@ -5,4 +5,4 @@ export { getDefaultProjectName } from "./utils/project.js";
|
|
|
5
5
|
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
6
6
|
export { Cache, PromptCache, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
7
7
|
// Update using pnpm bump-version
|
|
8
|
-
export const __version__ = "0.5.
|
|
8
|
+
export const __version__ = "0.5.23";
|
package/dist/schemas.d.ts
CHANGED
|
@@ -435,6 +435,60 @@ export type PromptSortField = "num_downloads" | "num_views" | "updated_at" | "nu
|
|
|
435
435
|
export interface LikePromptResponse {
|
|
436
436
|
likes: number;
|
|
437
437
|
}
|
|
438
|
+
export interface FileEntry {
|
|
439
|
+
type: "file";
|
|
440
|
+
content: string;
|
|
441
|
+
}
|
|
442
|
+
export interface AgentEntry {
|
|
443
|
+
type: "agent";
|
|
444
|
+
repo_handle: string;
|
|
445
|
+
commit_id?: string;
|
|
446
|
+
owner?: string;
|
|
447
|
+
commit_hash?: string;
|
|
448
|
+
}
|
|
449
|
+
export interface SkillEntry {
|
|
450
|
+
type: "skill";
|
|
451
|
+
repo_handle: string;
|
|
452
|
+
commit_id?: string;
|
|
453
|
+
owner?: string;
|
|
454
|
+
commit_hash?: string;
|
|
455
|
+
}
|
|
456
|
+
export type Entry = FileEntry | AgentEntry | SkillEntry;
|
|
457
|
+
/** The type of a non-prompt hub repo. */
|
|
458
|
+
export type HubRepoType = "agent" | "skill";
|
|
459
|
+
/**
|
|
460
|
+
* An agent pulled from hub.
|
|
461
|
+
*/
|
|
462
|
+
export interface AgentContext {
|
|
463
|
+
/** The commit ID. */
|
|
464
|
+
commit_id: string;
|
|
465
|
+
/** The commit hash. */
|
|
466
|
+
commit_hash: string;
|
|
467
|
+
/** The files in the agent. */
|
|
468
|
+
files: Record<string, Entry>;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* A skill pulled from hub.
|
|
472
|
+
*/
|
|
473
|
+
export interface SkillContext {
|
|
474
|
+
/** The commit ID. */
|
|
475
|
+
commit_id: string;
|
|
476
|
+
/** The commit hash. */
|
|
477
|
+
commit_hash: string;
|
|
478
|
+
/** The files in the skill. */
|
|
479
|
+
files: Record<string, Entry>;
|
|
480
|
+
}
|
|
481
|
+
/** Response body for `POST /directories/commits`. */
|
|
482
|
+
export interface DirectoryCommitResponse {
|
|
483
|
+
commit: {
|
|
484
|
+
/** The commit ID. */
|
|
485
|
+
id: string;
|
|
486
|
+
/** The commit hash. */
|
|
487
|
+
commit_hash: string;
|
|
488
|
+
/** When the commit was created. */
|
|
489
|
+
created_at: string;
|
|
490
|
+
};
|
|
491
|
+
}
|
|
438
492
|
export interface LangSmithSettings {
|
|
439
493
|
id: string;
|
|
440
494
|
display_name: string;
|
package/dist/utils/error.cjs
CHANGED
|
@@ -4,6 +4,7 @@ exports.ConflictingEndpointsError = exports.LangSmithNotFoundError = exports.Lan
|
|
|
4
4
|
exports.getInvalidPromptIdentifierMsg = getInvalidPromptIdentifierMsg;
|
|
5
5
|
exports.printErrorStackTrace = printErrorStackTrace;
|
|
6
6
|
exports.isLangSmithNotFoundError = isLangSmithNotFoundError;
|
|
7
|
+
exports.isLangSmithConflictError = isLangSmithConflictError;
|
|
7
8
|
exports.raiseForStatus = raiseForStatus;
|
|
8
9
|
exports.isConflictingEndpointsError = isConflictingEndpointsError;
|
|
9
10
|
/**
|
|
@@ -115,6 +116,12 @@ function isLangSmithNotFoundError(error) {
|
|
|
115
116
|
"name" in error &&
|
|
116
117
|
error?.name === "LangSmithNotFoundError");
|
|
117
118
|
}
|
|
119
|
+
function isLangSmithConflictError(error) {
|
|
120
|
+
return (error != null &&
|
|
121
|
+
typeof error === "object" &&
|
|
122
|
+
"name" in error &&
|
|
123
|
+
error?.name === "LangSmithConflictError");
|
|
124
|
+
}
|
|
118
125
|
/**
|
|
119
126
|
* Throws an appropriate error based on the response status and body.
|
|
120
127
|
*
|
package/dist/utils/error.d.ts
CHANGED
|
@@ -55,6 +55,7 @@ export declare class LangSmithNotFoundError extends Error {
|
|
|
55
55
|
constructor(message: string);
|
|
56
56
|
}
|
|
57
57
|
export declare function isLangSmithNotFoundError(error: unknown): error is LangSmithNotFoundError;
|
|
58
|
+
export declare function isLangSmithConflictError(error: unknown): error is LangSmithConflictError;
|
|
58
59
|
/**
|
|
59
60
|
* Throws an appropriate error based on the response status and body.
|
|
60
61
|
*
|
package/dist/utils/error.js
CHANGED
|
@@ -105,6 +105,12 @@ export function isLangSmithNotFoundError(error) {
|
|
|
105
105
|
"name" in error &&
|
|
106
106
|
error?.name === "LangSmithNotFoundError");
|
|
107
107
|
}
|
|
108
|
+
export function isLangSmithConflictError(error) {
|
|
109
|
+
return (error != null &&
|
|
110
|
+
typeof error === "object" &&
|
|
111
|
+
"name" in error &&
|
|
112
|
+
error?.name === "LangSmithConflictError");
|
|
113
|
+
}
|
|
108
114
|
/**
|
|
109
115
|
* Throws an appropriate error based on the response status and body.
|
|
110
116
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.estimateSerializedSize = estimateSerializedSize;
|
|
3
4
|
exports.serialize = serialize;
|
|
4
5
|
/* eslint-disable */
|
|
5
6
|
// @ts-nocheck
|
|
@@ -60,6 +61,233 @@ function createDefaultReplacer(userReplacer) {
|
|
|
60
61
|
return serializeWellKnownTypes(val);
|
|
61
62
|
};
|
|
62
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Estimate the serialized JSON byte size of a value without actually
|
|
66
|
+
* serializing it. Used on hot paths (enqueuing runs for batched tracing)
|
|
67
|
+
* where the exact serialized size is not required -- only a reasonable
|
|
68
|
+
* approximation for soft memory accounting.
|
|
69
|
+
*
|
|
70
|
+
* Walks the object graph in O(n) without allocating a JSON string,
|
|
71
|
+
* avoiding the event-loop blocking that JSON.stringify causes on large
|
|
72
|
+
* payloads.
|
|
73
|
+
*
|
|
74
|
+
* Accuracy notes (all estimates are approximate, never exact):
|
|
75
|
+
* - Strings: UTF-8 byte length via Buffer.byteLength when available,
|
|
76
|
+
* falling back to code-unit length for non-Node environments. Does
|
|
77
|
+
* not account for escape expansion (\", \\, control chars, surrogate
|
|
78
|
+
* escapes) which is usually a small fraction of total size.
|
|
79
|
+
* - Binary data (Buffer / typed arrays / ArrayBuffer / DataView): sized
|
|
80
|
+
* from their JSON.stringify representations where practical
|
|
81
|
+
* ({ type: "Buffer", data: [...] } for Buffer, keyed objects for typed
|
|
82
|
+
* arrays). DataView and ArrayBuffer themselves have no enumerable own
|
|
83
|
+
* properties and serialize as "{}". Each byte contributes ~3.5
|
|
84
|
+
* characters on average in Buffer's decimal-array representation
|
|
85
|
+
* (digit(s) + comma).
|
|
86
|
+
* - Other objects with toJSON(): we invoke toJSON() once and estimate
|
|
87
|
+
* the result. This matches JSON.stringify semantics for libraries
|
|
88
|
+
* like Decimal.js, Moment, Luxon, Mongoose documents, etc.
|
|
89
|
+
* - Cycles: detected via an ancestor-path set that is pushed/popped
|
|
90
|
+
* during recursion. This matches JSON.stringify semantics --
|
|
91
|
+
* repeated references that are *not* on the current ancestor chain
|
|
92
|
+
* (shared subobjects) are counted every time they appear, because
|
|
93
|
+
* JSON.stringify will serialize them every time.
|
|
94
|
+
* - No depth limit (JSON.stringify has none either).
|
|
95
|
+
*/
|
|
96
|
+
function estimateSerializedSize(value) {
|
|
97
|
+
try {
|
|
98
|
+
// Ancestor set for cycle detection. An object is only treated as
|
|
99
|
+
// circular if it appears on the current recursion path, not merely
|
|
100
|
+
// if it has been seen before elsewhere in the graph.
|
|
101
|
+
const ancestors = new Set();
|
|
102
|
+
// In Node / Bun, Buffer.byteLength is a fast native way to get UTF-8
|
|
103
|
+
// byte length without allocating an encoded copy. In other runtimes
|
|
104
|
+
// we fall back to code-unit length (a small under-estimate for
|
|
105
|
+
// non-ASCII text, which is acceptable for soft limits).
|
|
106
|
+
const byteLen = typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function"
|
|
107
|
+
? (s) => Buffer.byteLength(s, "utf8")
|
|
108
|
+
: (s) => s.length;
|
|
109
|
+
function estimateString(s) {
|
|
110
|
+
// +2 for the surrounding quotes. Escape expansion is not counted.
|
|
111
|
+
return byteLen(s) + 2;
|
|
112
|
+
}
|
|
113
|
+
// Size of a byte sequence when rendered as a JSON array of decimal
|
|
114
|
+
// numbers: "[b0,b1,b2,...]". Each byte averages ~3.5 chars (value 0-9
|
|
115
|
+
// => 1 char, 10-99 => 2 chars, 100-255 => 3 chars; weighted mean over
|
|
116
|
+
// a uniform distribution is ~2.81, plus one comma per element except
|
|
117
|
+
// the last). Round up to 4 bytes/element for a small safety margin.
|
|
118
|
+
function estimateByteArrayJson(byteLength) {
|
|
119
|
+
if (byteLength === 0)
|
|
120
|
+
return 2; // "[]"
|
|
121
|
+
return 2 + byteLength * 4;
|
|
122
|
+
}
|
|
123
|
+
// Returns true for values that JSON.stringify drops when they appear
|
|
124
|
+
// as an object property (as opposed to an array element, where they
|
|
125
|
+
// become "null").
|
|
126
|
+
function isDropped(v) {
|
|
127
|
+
return (v === undefined || typeof v === "function" || typeof v === "symbol");
|
|
128
|
+
}
|
|
129
|
+
// In arrays, undefined / function / symbol become "null" (4 bytes).
|
|
130
|
+
function estimateInArray(v) {
|
|
131
|
+
if (v === undefined || typeof v === "function" || typeof v === "symbol") {
|
|
132
|
+
return 4;
|
|
133
|
+
}
|
|
134
|
+
return estimate(v);
|
|
135
|
+
}
|
|
136
|
+
function estimate(val) {
|
|
137
|
+
if (val === null)
|
|
138
|
+
return 4; // "null"
|
|
139
|
+
if (val === undefined)
|
|
140
|
+
return 0; // top-level or property context; array handled separately
|
|
141
|
+
const t = typeof val;
|
|
142
|
+
if (t === "boolean")
|
|
143
|
+
return 5; // "true" / "false" upper bound
|
|
144
|
+
if (t === "number") {
|
|
145
|
+
if (!Number.isFinite(val))
|
|
146
|
+
return 4; // "null"
|
|
147
|
+
// Convert to string to get exact length. This is cheap for numbers
|
|
148
|
+
// (V8 caches small-number strings) and makes the estimate far
|
|
149
|
+
// tighter for common cases like integer arrays.
|
|
150
|
+
return val.toString().length;
|
|
151
|
+
}
|
|
152
|
+
if (t === "bigint") {
|
|
153
|
+
// Our replacer renders BigInt via .toString(), then JSON.stringify
|
|
154
|
+
// quotes it.
|
|
155
|
+
return val.toString().length + 2;
|
|
156
|
+
}
|
|
157
|
+
if (t === "string")
|
|
158
|
+
return estimateString(val);
|
|
159
|
+
if (t === "function" || t === "symbol")
|
|
160
|
+
return 0;
|
|
161
|
+
// Objects from here on.
|
|
162
|
+
const obj = val;
|
|
163
|
+
// Well-known types handled by our replacer.
|
|
164
|
+
if (obj instanceof Date)
|
|
165
|
+
return 26; // "2024-01-01T00:00:00.000Z"
|
|
166
|
+
if (obj instanceof RegExp)
|
|
167
|
+
return byteLen(obj.toString()) + 2;
|
|
168
|
+
if (obj instanceof Error) {
|
|
169
|
+
const name = obj.name ?? "";
|
|
170
|
+
const message = obj.message ?? "";
|
|
171
|
+
// {"name":"...","message":"..."}
|
|
172
|
+
return 22 + byteLen(name) + byteLen(message);
|
|
173
|
+
}
|
|
174
|
+
// Binary data types. These commonly appear in LLM payloads (images,
|
|
175
|
+
// audio) and their JSON representations vary widely.
|
|
176
|
+
if (typeof Buffer !== "undefined" && obj instanceof Buffer) {
|
|
177
|
+
// { "type": "Buffer", "data": [0, 1, 2, ...] }
|
|
178
|
+
return 28 + estimateByteArrayJson(obj.byteLength);
|
|
179
|
+
}
|
|
180
|
+
if (ArrayBuffer.isView(obj)) {
|
|
181
|
+
if (obj instanceof DataView) {
|
|
182
|
+
// DataView has no enumerable own properties; serializes as "{}".
|
|
183
|
+
return 2;
|
|
184
|
+
}
|
|
185
|
+
// Typed arrays serialize as {"0":v0,"1":v1,...} (keyed objects),
|
|
186
|
+
// which is much larger than a plain array would be. Per element
|
|
187
|
+
// cost: digits for index + digits for value + ":" + "," + quotes.
|
|
188
|
+
const len = obj.length ?? 0;
|
|
189
|
+
const isFloat = obj instanceof Float32Array || obj instanceof Float64Array;
|
|
190
|
+
// Index digits grow with len; worst-case per element:
|
|
191
|
+
// "NNN":V, where NNN = log10(len) digits and V depends on type.
|
|
192
|
+
// Loose but safe bounds: integer views ~12 chars/element, float
|
|
193
|
+
// views ~30 chars/element (Float32 ToString can be up to ~17 chars).
|
|
194
|
+
const perElement = isFloat ? 30 : 12;
|
|
195
|
+
return 2 + len * perElement;
|
|
196
|
+
}
|
|
197
|
+
if (obj instanceof ArrayBuffer) {
|
|
198
|
+
// Plain ArrayBuffer has no enumerable properties; serializes as "{}".
|
|
199
|
+
return 2;
|
|
200
|
+
}
|
|
201
|
+
if (ancestors.has(obj)) {
|
|
202
|
+
// Cycle: our decirc fallback replaces with { result: "[Circular]" }.
|
|
203
|
+
return 24;
|
|
204
|
+
}
|
|
205
|
+
// Custom toJSON (Decimal.js, Moment, Luxon, Mongoose docs, etc.).
|
|
206
|
+
// This runs after explicit built-in / binary cases above so known
|
|
207
|
+
// types (for example Buffer) use their dedicated fast-path sizing
|
|
208
|
+
// logic instead of duck-typing through toJSON().
|
|
209
|
+
if (typeof obj.toJSON === "function") {
|
|
210
|
+
let projected;
|
|
211
|
+
try {
|
|
212
|
+
projected = obj.toJSON("");
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// If toJSON throws, JSON.stringify would also throw and our
|
|
216
|
+
// serializer would emit "[Unserializable]" (~16 bytes).
|
|
217
|
+
return 16;
|
|
218
|
+
}
|
|
219
|
+
ancestors.add(obj);
|
|
220
|
+
const size = estimate(projected);
|
|
221
|
+
ancestors.delete(obj);
|
|
222
|
+
return size;
|
|
223
|
+
}
|
|
224
|
+
ancestors.add(obj);
|
|
225
|
+
let size;
|
|
226
|
+
if (Array.isArray(obj)) {
|
|
227
|
+
size = 2; // []
|
|
228
|
+
const len = obj.length;
|
|
229
|
+
for (let i = 0; i < len; i++) {
|
|
230
|
+
size += estimateInArray(obj[i]);
|
|
231
|
+
if (i < len - 1)
|
|
232
|
+
size += 1; // comma
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else if (obj instanceof Map) {
|
|
236
|
+
// Rendered as { k: v, ... } via Object.fromEntries.
|
|
237
|
+
size = 2;
|
|
238
|
+
let emitted = 0;
|
|
239
|
+
for (const [k, v] of obj) {
|
|
240
|
+
if (isDropped(v))
|
|
241
|
+
continue;
|
|
242
|
+
if (emitted > 0)
|
|
243
|
+
size += 1; // comma
|
|
244
|
+
const keyStr = typeof k === "string" ? k : String(k);
|
|
245
|
+
size += byteLen(keyStr) + 3; // "key":
|
|
246
|
+
size += estimate(v);
|
|
247
|
+
emitted++;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (obj instanceof Set) {
|
|
251
|
+
// Rendered as [v, ...] via Array.from.
|
|
252
|
+
size = 2;
|
|
253
|
+
let emitted = 0;
|
|
254
|
+
for (const v of obj) {
|
|
255
|
+
if (emitted > 0)
|
|
256
|
+
size += 1; // comma
|
|
257
|
+
size += estimateInArray(v);
|
|
258
|
+
emitted++;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
size = 2; // {}
|
|
263
|
+
let emitted = 0;
|
|
264
|
+
// Object.keys only returns own enumerable string keys, matching
|
|
265
|
+
// JSON.stringify.
|
|
266
|
+
const keys = Object.keys(obj);
|
|
267
|
+
for (let i = 0; i < keys.length; i++) {
|
|
268
|
+
const key = keys[i];
|
|
269
|
+
const v = obj[key];
|
|
270
|
+
if (isDropped(v))
|
|
271
|
+
continue;
|
|
272
|
+
if (emitted > 0)
|
|
273
|
+
size += 1; // comma
|
|
274
|
+
size += byteLen(key) + 3; // "key":
|
|
275
|
+
size += estimate(v);
|
|
276
|
+
emitted++;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
ancestors.delete(obj);
|
|
280
|
+
return size;
|
|
281
|
+
}
|
|
282
|
+
return estimate(value);
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// If the estimator itself hits an unexpected edge case, fall back to the
|
|
286
|
+
// exact serialized size. This preserves correctness of queue-size
|
|
287
|
+
// accounting at the cost of a slower hot path for that one payload.
|
|
288
|
+
return serialize(value).length;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
63
291
|
// Regular stringify
|
|
64
292
|
function serialize(obj, errorContext, replacer, spacer, options) {
|
|
65
293
|
try {
|
|
@@ -1 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estimate the serialized JSON byte size of a value without actually
|
|
3
|
+
* serializing it. Used on hot paths (enqueuing runs for batched tracing)
|
|
4
|
+
* where the exact serialized size is not required -- only a reasonable
|
|
5
|
+
* approximation for soft memory accounting.
|
|
6
|
+
*
|
|
7
|
+
* Walks the object graph in O(n) without allocating a JSON string,
|
|
8
|
+
* avoiding the event-loop blocking that JSON.stringify causes on large
|
|
9
|
+
* payloads.
|
|
10
|
+
*
|
|
11
|
+
* Accuracy notes (all estimates are approximate, never exact):
|
|
12
|
+
* - Strings: UTF-8 byte length via Buffer.byteLength when available,
|
|
13
|
+
* falling back to code-unit length for non-Node environments. Does
|
|
14
|
+
* not account for escape expansion (\", \\, control chars, surrogate
|
|
15
|
+
* escapes) which is usually a small fraction of total size.
|
|
16
|
+
* - Binary data (Buffer / typed arrays / ArrayBuffer / DataView): sized
|
|
17
|
+
* from their JSON.stringify representations where practical
|
|
18
|
+
* ({ type: "Buffer", data: [...] } for Buffer, keyed objects for typed
|
|
19
|
+
* arrays). DataView and ArrayBuffer themselves have no enumerable own
|
|
20
|
+
* properties and serialize as "{}". Each byte contributes ~3.5
|
|
21
|
+
* characters on average in Buffer's decimal-array representation
|
|
22
|
+
* (digit(s) + comma).
|
|
23
|
+
* - Other objects with toJSON(): we invoke toJSON() once and estimate
|
|
24
|
+
* the result. This matches JSON.stringify semantics for libraries
|
|
25
|
+
* like Decimal.js, Moment, Luxon, Mongoose documents, etc.
|
|
26
|
+
* - Cycles: detected via an ancestor-path set that is pushed/popped
|
|
27
|
+
* during recursion. This matches JSON.stringify semantics --
|
|
28
|
+
* repeated references that are *not* on the current ancestor chain
|
|
29
|
+
* (shared subobjects) are counted every time they appear, because
|
|
30
|
+
* JSON.stringify will serialize them every time.
|
|
31
|
+
* - No depth limit (JSON.stringify has none either).
|
|
32
|
+
*/
|
|
33
|
+
export declare function estimateSerializedSize(value: unknown): number;
|
|
1
34
|
export declare function serialize(obj: any, errorContext?: any, replacer?: any, spacer?: any, options?: any): Uint8Array<ArrayBuffer>;
|