@hue-run/sdk 0.15.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLI.md +30 -21
- package/EVALUATIONS.md +1 -1
- package/README.md +71 -49
- package/dist/blobs.d.ts +35 -17
- package/dist/blobs.js +141 -75
- package/dist/cli/env-file.d.ts +2 -0
- package/dist/cli/env-file.js +2 -0
- package/dist/cli/eval-direct.d.ts +3 -2
- package/dist/cli/eval-direct.js +49 -6
- package/dist/cli/eval.js +109 -22
- package/dist/cli/login.js +2 -3
- package/dist/client.d.ts +3 -1
- package/dist/client.js +70 -20
- package/dist/evals/attempt.d.ts +1 -1
- package/dist/evals/attempt.js +1 -1
- package/dist/evals/checkpoint.d.ts +6 -2
- package/dist/evals/checkpoint.js +75 -12
- package/dist/evals/files.js +12 -0
- package/dist/evals/runner.d.ts +9 -0
- package/dist/evals/runner.js +63 -10
- package/dist/evals/scorer-publication.js +1 -1
- package/dist/evals/simulation.js +4 -2
- package/dist/inline-files.d.ts +38 -29
- package/dist/inline-files.js +288 -83
- package/dist/privacy.d.ts +1 -1
- package/dist/privacy.js +4 -10
- package/dist/safety.d.ts +1 -0
- package/dist/safety.js +7 -1
- package/dist/snapshot.d.ts +6 -3
- package/dist/snapshot.js +70 -25
- package/dist/transport.d.ts +11 -0
- package/dist/transport.js +296 -20
- package/dist/types.d.ts +7 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -10
package/dist/snapshot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createTraceState } from "@opentelemetry/api";
|
|
2
2
|
import { types as utilTypes } from "node:util";
|
|
3
3
|
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
4
|
-
import { hashInlineFiles,
|
|
4
|
+
import { hashInlineFiles, hashNestedInlineFiles, INLINE_FILE_TEXT_PER_RECORD, MAX_INLINE_FILE_TEXT, isMessageKey, mayInlineFiles, } from "./inline-files.js";
|
|
5
5
|
import { scrubsToolCredentials, scrubToolCredentials } from "./tool-definitions.js";
|
|
6
6
|
import { MAX_RECORD_NODES } from "./config.js";
|
|
7
7
|
import { truncatedMarker } from "./privacy.js";
|
|
@@ -30,6 +30,8 @@ class Snapshot {
|
|
|
30
30
|
captureContent;
|
|
31
31
|
valueUnits;
|
|
32
32
|
hold;
|
|
33
|
+
memo;
|
|
34
|
+
traceId;
|
|
33
35
|
bytes = 512;
|
|
34
36
|
unresolvedResource = false;
|
|
35
37
|
/** The value strings this snapshot cut to `valueUnits`; export recognizes them, so the
|
|
@@ -38,28 +40,36 @@ class Snapshot {
|
|
|
38
40
|
nodes = 0;
|
|
39
41
|
ancestors = new Set();
|
|
40
42
|
copied = new Map();
|
|
43
|
+
attributesCopied = new Map();
|
|
44
|
+
ownAttributesCopied = new Map();
|
|
41
45
|
hashed = new Map();
|
|
46
|
+
nestedHashed = new Map();
|
|
42
47
|
inspected = 0;
|
|
43
48
|
/** Bytes of values held whole for upload, charged to the held-value budget. */
|
|
44
49
|
held = 0;
|
|
45
50
|
/** Set while the span's own attributes are copied: only they may be held for upload. */
|
|
46
51
|
own = false;
|
|
47
|
-
/** The span's own messages whose
|
|
52
|
+
/** The span's own messages whose inline media shrank to their digest when queued, by
|
|
48
53
|
* attribute: the text queued (cut or not), and how many files it lost. */
|
|
49
54
|
digested = new Map();
|
|
50
55
|
/** How many files each message text {@link inlineFiles} hashed replaced by their digest. */
|
|
51
56
|
hashedFiles = new Map();
|
|
57
|
+
/** The span's own message attributes inspected within the record's allowance, whether here or
|
|
58
|
+
* left to export for a message held whole: export inspects only these. */
|
|
59
|
+
inspectedKeys = new Set();
|
|
52
60
|
/**
|
|
53
61
|
* In metadata-only mode the recorded messages, which export strips, are not copied at all. A
|
|
54
62
|
* value string (an attribute's, an event's or link's attribute's, a log body or a status
|
|
55
63
|
* message) longer than `valueUnits` is cut to that length: export cuts it to the value cap
|
|
56
64
|
* anyway, and charging it whole could drop the record before that cut ever ran.
|
|
57
65
|
*/
|
|
58
|
-
constructor(limit, captureContent = true, valueUnits = Infinity, hold) {
|
|
66
|
+
constructor(limit, captureContent = true, valueUnits = Infinity, hold, memo, traceId = "") {
|
|
59
67
|
this.limit = limit;
|
|
60
68
|
this.captureContent = captureContent;
|
|
61
69
|
this.valueUnits = valueUnits;
|
|
62
70
|
this.hold = hold;
|
|
71
|
+
this.memo = memo;
|
|
72
|
+
this.traceId = traceId;
|
|
63
73
|
}
|
|
64
74
|
/** Whether the held-value budget takes `bytes` more, charging them when it does. */
|
|
65
75
|
holds(bytes) {
|
|
@@ -74,7 +84,7 @@ class Snapshot {
|
|
|
74
84
|
* longer than the queued value length or bytes over the cap, within the held-value budget, and
|
|
75
85
|
* a recorded message that may inline a large file kept as it is (export uploads the file).
|
|
76
86
|
* Undefined for a value copied as before; text over the length the budget cannot hold is then
|
|
77
|
-
* cut and its
|
|
87
|
+
* cut and its inline media shrink to their digest, as before uploads existed.
|
|
78
88
|
*/
|
|
79
89
|
heldValue(key, value) {
|
|
80
90
|
if (!this.hold || !this.own)
|
|
@@ -86,9 +96,16 @@ class Snapshot {
|
|
|
86
96
|
if (this.bytes + fallback > this.limit || !this.holds(value.length * 2))
|
|
87
97
|
return undefined;
|
|
88
98
|
this.charge(fallback);
|
|
99
|
+
// Export parses the held message; its inspection allowance is taken here, in order.
|
|
100
|
+
if (value.length <= MAX_INLINE_FILE_TEXT &&
|
|
101
|
+
mayInlineFiles(key, value) &&
|
|
102
|
+
this.inspected + value.length <= INLINE_FILE_TEXT_PER_RECORD) {
|
|
103
|
+
this.inspected += value.length;
|
|
104
|
+
this.inspectedKeys.add(key);
|
|
105
|
+
}
|
|
89
106
|
return { value };
|
|
90
107
|
}
|
|
91
|
-
// Within the queued length: a recorded message holding
|
|
108
|
+
// Within the queued length: a recorded message holding an inline media part is held whole
|
|
92
109
|
// for export to upload the file, within the held-value budget, and the queue is charged
|
|
93
110
|
// its copy with the files as their digest, as before. Past the budget, the files shrink to
|
|
94
111
|
// their digest when queued, as before uploads existed.
|
|
@@ -119,7 +136,12 @@ class Snapshot {
|
|
|
119
136
|
throw new BudgetExceeded("Telemetry byte budget exceeded");
|
|
120
137
|
}
|
|
121
138
|
mark() {
|
|
122
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
bytes: this.bytes,
|
|
141
|
+
nodes: this.nodes,
|
|
142
|
+
copied: this.copied.size,
|
|
143
|
+
attributesCopied: this.attributesCopied.size,
|
|
144
|
+
};
|
|
123
145
|
}
|
|
124
146
|
/** Back to `mark`, forgetting the values copied since: a later copy must not reuse a partial
|
|
125
147
|
* copy of an item that was left out. */
|
|
@@ -131,6 +153,10 @@ class Snapshot {
|
|
|
131
153
|
for (const key of [...this.copied.keys()])
|
|
132
154
|
if (index++ >= mark.copied)
|
|
133
155
|
this.copied.delete(key);
|
|
156
|
+
index = 0;
|
|
157
|
+
for (const key of [...this.attributesCopied.keys()])
|
|
158
|
+
if (index++ >= mark.attributesCopied)
|
|
159
|
+
this.attributesCopied.delete(key);
|
|
134
160
|
}
|
|
135
161
|
/**
|
|
136
162
|
* As many of a span's newest `items` (its events or links) as the record's budget still holds,
|
|
@@ -163,7 +189,7 @@ class Snapshot {
|
|
|
163
189
|
return { kept, dropped: count - kept.length };
|
|
164
190
|
}
|
|
165
191
|
/**
|
|
166
|
-
* An attribute map. A
|
|
192
|
+
* An attribute map. A inline media part in a message attribute shrinks to its digest before it
|
|
167
193
|
* is charged: export replaces it anyway, and charging the file could drop the whole record.
|
|
168
194
|
*/
|
|
169
195
|
attributes(value) {
|
|
@@ -179,22 +205,32 @@ class Snapshot {
|
|
|
179
205
|
this.own = false;
|
|
180
206
|
}
|
|
181
207
|
}
|
|
182
|
-
/** A message attribute with its
|
|
183
|
-
*
|
|
184
|
-
*
|
|
208
|
+
/** A message attribute with its inline media hashed. Own and nested attributes cache
|
|
209
|
+
* separately because small binary media stays inline only in nested attributes. A record
|
|
210
|
+
* inspects at most {@link INLINE_FILE_TEXT_PER_RECORD} code units in all; beyond that,
|
|
211
|
+
* messages are charged as recorded. */
|
|
185
212
|
inlineFiles(key, value) {
|
|
186
|
-
|
|
187
|
-
|
|
213
|
+
if (typeof value !== "string" ||
|
|
214
|
+
value.length > MAX_INLINE_FILE_TEXT ||
|
|
215
|
+
!mayInlineFiles(key, value))
|
|
188
216
|
return value;
|
|
189
|
-
|
|
190
|
-
|
|
217
|
+
const hashed = this.own ? this.hashed : this.nestedHashed;
|
|
218
|
+
if (hashed.has(value)) {
|
|
219
|
+
if (this.own)
|
|
220
|
+
this.inspectedKeys.add(key);
|
|
221
|
+
return hashed.get(value);
|
|
222
|
+
}
|
|
191
223
|
if (this.inspected + value.length > INLINE_FILE_TEXT_PER_RECORD)
|
|
192
224
|
return value;
|
|
193
225
|
this.inspected += value.length;
|
|
226
|
+
if (this.own)
|
|
227
|
+
this.inspectedKeys.add(key);
|
|
194
228
|
const count = { files: 0 };
|
|
195
|
-
const result =
|
|
196
|
-
|
|
197
|
-
|
|
229
|
+
const result = this.own
|
|
230
|
+
? hashInlineFiles(key, value, count, this.memo, this.traceId)
|
|
231
|
+
: hashNestedInlineFiles(key, value);
|
|
232
|
+
hashed.set(value, result);
|
|
233
|
+
if (this.own && count.files)
|
|
198
234
|
this.hashedFiles.set(value, count.files);
|
|
199
235
|
return result;
|
|
200
236
|
}
|
|
@@ -266,8 +302,15 @@ class Snapshot {
|
|
|
266
302
|
throw new TypeError("Telemetry proxies are unsupported");
|
|
267
303
|
if (this.ancestors.has(value))
|
|
268
304
|
throw new TypeError("Cyclic telemetry value");
|
|
269
|
-
|
|
270
|
-
|
|
305
|
+
// One object can be reused as own attributes, nested attributes and an ordinary log body.
|
|
306
|
+
// Their copies differ: only attributes inspect media, and only own attributes upload it.
|
|
307
|
+
const copies = shape === "attributes"
|
|
308
|
+
? this.own
|
|
309
|
+
? this.ownAttributesCopied
|
|
310
|
+
: this.attributesCopied
|
|
311
|
+
: this.copied;
|
|
312
|
+
if (copies.has(value))
|
|
313
|
+
return copies.get(value);
|
|
271
314
|
if (utilTypes.isUint8Array(value)) {
|
|
272
315
|
// Own accessors/subclasses cannot disguise the retained byte count.
|
|
273
316
|
// A length-tracking SharedArrayBuffer view can grow on another thread
|
|
@@ -277,14 +320,14 @@ class Snapshot {
|
|
|
277
320
|
this.charge(length);
|
|
278
321
|
const copy = new Uint8Array(length);
|
|
279
322
|
typedArraySet.call(copy, value);
|
|
280
|
-
|
|
323
|
+
copies.set(value, copy);
|
|
281
324
|
return copy;
|
|
282
325
|
}
|
|
283
326
|
const array = Array.isArray(value);
|
|
284
327
|
if (!array && ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
285
328
|
throw new TypeError("Telemetry must contain data objects");
|
|
286
329
|
const copy = array ? [] : Object.create(null);
|
|
287
|
-
|
|
330
|
+
copies.set(value, copy);
|
|
288
331
|
this.ancestors.add(value);
|
|
289
332
|
if (array) {
|
|
290
333
|
if (value.length > MAX_RECORD_NODES)
|
|
@@ -316,7 +359,7 @@ class Snapshot {
|
|
|
316
359
|
? this.scrubbedBeforeCut(key, this.inlineFiles(key, source))
|
|
317
360
|
: source, depth + 1, shape === "event" && key === "attributes" ? "attributes" : "value", content || shape === "attributes");
|
|
318
361
|
copy[key] = copied;
|
|
319
|
-
// A span's own message whose
|
|
362
|
+
// A span's own message whose inline media shrank to their digest is named as it
|
|
320
363
|
// was queued, cut or not, so export reports each file as not uploaded.
|
|
321
364
|
const files = this.own && shape === "attributes" && typeof source === "string"
|
|
322
365
|
? this.hashedFiles.get(source)
|
|
@@ -360,7 +403,7 @@ class Snapshot {
|
|
|
360
403
|
if (value == null || Object.hasOwn(attributes, key))
|
|
361
404
|
continue;
|
|
362
405
|
this.charge(key.length * 2 + 16);
|
|
363
|
-
attributes[key] = this.copy(this.scrubbedBeforeCut(key, value), 0, "value", true);
|
|
406
|
+
attributes[key] = this.copy(this.scrubbedBeforeCut(key, this.inlineFiles(key, value)), 0, "value", true);
|
|
364
407
|
}
|
|
365
408
|
return resourceFromAttributes(attributes, { schemaUrl: this.copy(source.schemaUrl) });
|
|
366
409
|
}
|
|
@@ -368,8 +411,8 @@ class Snapshot {
|
|
|
368
411
|
function contextReader(context) {
|
|
369
412
|
return () => context;
|
|
370
413
|
}
|
|
371
|
-
export function snapshotSpan(source, limit, captureContent = true, valueUnits = Infinity, hold) {
|
|
372
|
-
const snapshot = new Snapshot(limit, captureContent, valueUnits, hold);
|
|
414
|
+
export function snapshotSpan(source, limit, captureContent = true, valueUnits = Infinity, hold, memo) {
|
|
415
|
+
const snapshot = new Snapshot(limit, captureContent, valueUnits, hold, memo, source.spanContext().traceId);
|
|
373
416
|
const context = snapshot.context(source.spanContext());
|
|
374
417
|
const fields = snapshot.copy({
|
|
375
418
|
name: source.name,
|
|
@@ -416,6 +459,7 @@ export function snapshotSpan(source, limit, captureContent = true, valueUnits =
|
|
|
416
459
|
cut: snapshot.cut,
|
|
417
460
|
held: snapshot.held,
|
|
418
461
|
digested: snapshot.digested,
|
|
462
|
+
inspected: snapshot.inspectedKeys,
|
|
419
463
|
};
|
|
420
464
|
}
|
|
421
465
|
export function snapshotLog(source, limit, captureContent = true, valueUnits = Infinity) {
|
|
@@ -462,5 +506,6 @@ export function snapshotLog(source, limit, captureContent = true, valueUnits = I
|
|
|
462
506
|
cut: snapshot.cut,
|
|
463
507
|
held: 0,
|
|
464
508
|
digested: new Map(),
|
|
509
|
+
inspected: new Set(),
|
|
465
510
|
};
|
|
466
511
|
}
|
package/dist/transport.d.ts
CHANGED
|
@@ -79,11 +79,17 @@ export declare class HueTransport {
|
|
|
79
79
|
private holdsReleased;
|
|
80
80
|
private admissionCuts;
|
|
81
81
|
private admissionDigests;
|
|
82
|
+
private admissionInspected;
|
|
82
83
|
/** Uploads values over the inline limit apart from their spans; absent when disabled. */
|
|
83
84
|
private uploader?;
|
|
84
85
|
/** Bytes of values over the inline limit queued spans hold whole for upload, and each span's. */
|
|
85
86
|
private heldBytes;
|
|
86
87
|
private held;
|
|
88
|
+
private mediaMemo;
|
|
89
|
+
private media;
|
|
90
|
+
private mediaOwners;
|
|
91
|
+
private mediaTimer?;
|
|
92
|
+
private mediaFinalizer;
|
|
87
93
|
private uploaded;
|
|
88
94
|
private uploadFallbacks;
|
|
89
95
|
constructor(options: HueOptions);
|
|
@@ -98,6 +104,11 @@ export declare class HueTransport {
|
|
|
98
104
|
private announceLiveSpans;
|
|
99
105
|
private stopLiveTimer;
|
|
100
106
|
private stopLiveSpans;
|
|
107
|
+
private mediaIdentity;
|
|
108
|
+
private releaseMedia;
|
|
109
|
+
private protectMedia;
|
|
110
|
+
private releaseMediaIdentity;
|
|
111
|
+
private sweepMedia;
|
|
101
112
|
/** Bounded: a trace whose root never arrives (an abandoned run) gives way to newer ones. */
|
|
102
113
|
private countDropped;
|
|
103
114
|
/** Cumulative counters and current queue gauges. */
|