@frugalco/frugal-sdk-node 0.3.0 → 0.5.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/README.md +73 -12
- package/dist/block-hash-lru.d.ts +8 -1
- package/dist/block-hash-lru.d.ts.map +1 -1
- package/dist/block-hash-lru.js +13 -4
- package/dist/block-hash-lru.js.map +1 -1
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +218 -27
- package/dist/config.js.map +1 -1
- package/dist/duplicate-filter.d.ts +46 -0
- package/dist/duplicate-filter.d.ts.map +1 -0
- package/dist/duplicate-filter.js +168 -0
- package/dist/duplicate-filter.js.map +1 -0
- package/dist/instrument.d.ts +33 -0
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +277 -21
- package/dist/instrument.js.map +1 -1
- package/dist/model-cap.d.ts +24 -0
- package/dist/model-cap.d.ts.map +1 -0
- package/dist/model-cap.js +72 -0
- package/dist/model-cap.js.map +1 -0
- package/dist/otel.d.ts +32 -3
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +203 -7
- package/dist/otel.js.map +1 -1
- package/dist/prompt-analyzer.d.ts +12 -1
- package/dist/prompt-analyzer.d.ts.map +1 -1
- package/dist/prompt-analyzer.js +185 -14
- package/dist/prompt-analyzer.js.map +1 -1
- package/dist/providers.d.ts +1 -0
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +4 -1
- package/dist/providers.js.map +1 -1
- package/dist/semconv.d.ts +14 -0
- package/dist/semconv.d.ts.map +1 -1
- package/dist/semconv.js +38 -2
- package/dist/semconv.js.map +1 -1
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +15 -2
- package/dist/streams.js.map +1 -1
- package/dist/track.d.ts +18 -0
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +4 -1
- package/dist/track.js.map +1 -1
- package/dist/wrappers/anthropic.d.ts.map +1 -1
- package/dist/wrappers/anthropic.js +9 -1
- package/dist/wrappers/anthropic.js.map +1 -1
- package/dist/wrappers/batch.d.ts +11 -0
- package/dist/wrappers/batch.d.ts.map +1 -0
- package/dist/wrappers/batch.js +338 -0
- package/dist/wrappers/batch.js.map +1 -0
- package/dist/wrappers/openai.d.ts.map +1 -1
- package/dist/wrappers/openai.js +37 -30
- package/dist/wrappers/openai.js.map +1 -1
- package/dist/wrappers/patching.d.ts +10 -0
- package/dist/wrappers/patching.d.ts.map +1 -0
- package/dist/wrappers/patching.js +38 -0
- package/dist/wrappers/patching.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Config } from "./config.js";
|
|
2
|
+
import { DUP_FIRST_SEEN, DUP_REPEAT_SEEN } from "./semconv.js";
|
|
3
|
+
export type DupState = typeof DUP_FIRST_SEEN | typeof DUP_REPEAT_SEEN;
|
|
4
|
+
export declare class RotatingBloomFilter {
|
|
5
|
+
private readonly m;
|
|
6
|
+
private readonly k;
|
|
7
|
+
private readonly generations;
|
|
8
|
+
private readonly rotateMs;
|
|
9
|
+
private readonly bytesPerGen;
|
|
10
|
+
private bits;
|
|
11
|
+
private activeIndex;
|
|
12
|
+
private genStartMs;
|
|
13
|
+
private disabled;
|
|
14
|
+
private insertsSinceCheck;
|
|
15
|
+
private saturationWarned;
|
|
16
|
+
constructor(opts: {
|
|
17
|
+
capacity: number;
|
|
18
|
+
fpRate: number;
|
|
19
|
+
generations: number;
|
|
20
|
+
windowSeconds: number;
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Classify a signature and insert it. Returns null when the filter is
|
|
24
|
+
* disabled (bit-array allocation failed — latched for the process lifetime
|
|
25
|
+
* so the allocation is not retried on every call).
|
|
26
|
+
*
|
|
27
|
+
* The clock defaults to performance.now() (monotonic): rotation must not
|
|
28
|
+
* freeze when NTP steps the wall clock backward.
|
|
29
|
+
*/
|
|
30
|
+
seenBefore(signature: string, nowMs?: number): DupState | null;
|
|
31
|
+
clear(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Warn (once per fill, re-armed by clear()) when the filter is saturating.
|
|
34
|
+
* Membership tests the UNION of all generations, so occupancy is measured on
|
|
35
|
+
* the union too — measuring only the active generation would let two
|
|
36
|
+
* generations at 49% (union ~74%) pass silently. Past ~50% union fill the
|
|
37
|
+
* effective false-positive rate is far above the configured target and the
|
|
38
|
+
* metric drifts toward all-repeat_seen.
|
|
39
|
+
*/
|
|
40
|
+
private maybeWarnSaturation;
|
|
41
|
+
private rotate;
|
|
42
|
+
private positions;
|
|
43
|
+
}
|
|
44
|
+
export declare function getSharedDuplicateFilter(config: Config): RotatingBloomFilter | null;
|
|
45
|
+
export declare function resetSharedDuplicateFilterForTests(): void;
|
|
46
|
+
//# sourceMappingURL=duplicate-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-filter.d.ts","sourceRoot":"","sources":["../src/duplicate-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,OAAO,cAAc,GAAG,OAAO,eAAe,CAAC;AAyBtE,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAAS;gBAErB,IAAI,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;KACvB;IASD;;;;;;;OAOG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAA0B,GAAG,QAAQ,GAAG,IAAI;IAwDjF,KAAK,IAAI,IAAI;IAQb;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,SAAS;CASlB;AAID,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAWnF;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAEzD"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { emitLog, emitLogOnce } from "./debug.js";
|
|
2
|
+
import { DUP_FIRST_SEEN, DUP_REPEAT_SEEN } from "./semconv.js";
|
|
3
|
+
function bloomParams(capacity, fpRate) {
|
|
4
|
+
const N = Math.max(1, Math.floor(capacity));
|
|
5
|
+
const p = Math.min(Math.max(fpRate, 1e-6), 0.5);
|
|
6
|
+
const ln2 = Math.LN2;
|
|
7
|
+
const m = Math.max(8, Math.ceil((-N * Math.log(p)) / (ln2 * ln2)));
|
|
8
|
+
const k = Math.max(1, Math.round((m / N) * ln2));
|
|
9
|
+
return { m, k };
|
|
10
|
+
}
|
|
11
|
+
// How often (in insertions) to measure occupancy for the saturation warning.
|
|
12
|
+
// Counting set bits is O(m/8) bytes, so amortizing over 1024 inserts keeps the
|
|
13
|
+
// check negligible even at the capacity clamp.
|
|
14
|
+
const SATURATION_CHECK_INTERVAL = 1024;
|
|
15
|
+
// Union occupancy at which the false-positive rate is degraded badly enough to
|
|
16
|
+
// warn: at 50% fill the FP rate is ~(0.5)^k, orders of magnitude above the
|
|
17
|
+
// configured target, and rising fast.
|
|
18
|
+
const SATURATION_FILL_THRESHOLD = 0.5;
|
|
19
|
+
const POPCOUNT = new Uint8Array(256);
|
|
20
|
+
for (let i = 0; i < 256; i++) {
|
|
21
|
+
POPCOUNT[i] = (i & 1) + POPCOUNT[i >> 1];
|
|
22
|
+
}
|
|
23
|
+
export class RotatingBloomFilter {
|
|
24
|
+
m;
|
|
25
|
+
k;
|
|
26
|
+
generations;
|
|
27
|
+
rotateMs;
|
|
28
|
+
bytesPerGen;
|
|
29
|
+
bits = null;
|
|
30
|
+
activeIndex = 0;
|
|
31
|
+
genStartMs = 0;
|
|
32
|
+
disabled = false;
|
|
33
|
+
insertsSinceCheck = 0;
|
|
34
|
+
saturationWarned = false;
|
|
35
|
+
constructor(opts) {
|
|
36
|
+
const { m, k } = bloomParams(opts.capacity, opts.fpRate);
|
|
37
|
+
this.m = m;
|
|
38
|
+
this.k = k;
|
|
39
|
+
this.generations = Math.max(1, Math.floor(opts.generations));
|
|
40
|
+
this.rotateMs = Math.max(1, (opts.windowSeconds * 1000) / this.generations);
|
|
41
|
+
this.bytesPerGen = Math.ceil(m / 8);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Classify a signature and insert it. Returns null when the filter is
|
|
45
|
+
* disabled (bit-array allocation failed — latched for the process lifetime
|
|
46
|
+
* so the allocation is not retried on every call).
|
|
47
|
+
*
|
|
48
|
+
* The clock defaults to performance.now() (monotonic): rotation must not
|
|
49
|
+
* freeze when NTP steps the wall clock backward.
|
|
50
|
+
*/
|
|
51
|
+
seenBefore(signature, nowMs = performance.now()) {
|
|
52
|
+
if (this.disabled)
|
|
53
|
+
return null;
|
|
54
|
+
if (this.bits === null) {
|
|
55
|
+
try {
|
|
56
|
+
this.bits = Array.from({ length: this.generations }, () => new Uint8Array(this.bytesPerGen));
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
this.disabled = true;
|
|
60
|
+
emitLogOnce("duplicate_filter_alloc_failed", "error", `duplicate filter allocation failed (${this.generations} × ${this.bytesPerGen} bytes); duplicate detection disabled for this process. Lower FRUGAL_DUPLICATE_CAPACITY / FRUGAL_DUPLICATE_GENERATIONS.`);
|
|
61
|
+
// Rethrow once so the caller records a single internal_errors point;
|
|
62
|
+
// every later call short-circuits on the latch above.
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
this.genStartMs = nowMs;
|
|
66
|
+
}
|
|
67
|
+
this.rotate(nowMs);
|
|
68
|
+
const positions = this.positions(signature);
|
|
69
|
+
const bits = this.bits;
|
|
70
|
+
let present = true;
|
|
71
|
+
for (const pos of positions) {
|
|
72
|
+
const byte = pos >> 3;
|
|
73
|
+
const mask = 1 << (pos & 7);
|
|
74
|
+
let anySet = false;
|
|
75
|
+
for (let g = 0; g < this.generations; g++) {
|
|
76
|
+
if ((bits[g][byte] & mask) !== 0) {
|
|
77
|
+
anySet = true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!anySet) {
|
|
82
|
+
present = false;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const active = bits[this.activeIndex];
|
|
87
|
+
for (const pos of positions) {
|
|
88
|
+
active[pos >> 3] |= 1 << (pos & 7);
|
|
89
|
+
}
|
|
90
|
+
if (++this.insertsSinceCheck >= SATURATION_CHECK_INTERVAL) {
|
|
91
|
+
this.insertsSinceCheck = 0;
|
|
92
|
+
this.maybeWarnSaturation();
|
|
93
|
+
}
|
|
94
|
+
return present ? DUP_REPEAT_SEEN : DUP_FIRST_SEEN;
|
|
95
|
+
}
|
|
96
|
+
clear() {
|
|
97
|
+
this.bits = null;
|
|
98
|
+
this.activeIndex = 0;
|
|
99
|
+
this.genStartMs = 0;
|
|
100
|
+
this.insertsSinceCheck = 0;
|
|
101
|
+
this.saturationWarned = false;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Warn (once per fill, re-armed by clear()) when the filter is saturating.
|
|
105
|
+
* Membership tests the UNION of all generations, so occupancy is measured on
|
|
106
|
+
* the union too — measuring only the active generation would let two
|
|
107
|
+
* generations at 49% (union ~74%) pass silently. Past ~50% union fill the
|
|
108
|
+
* effective false-positive rate is far above the configured target and the
|
|
109
|
+
* metric drifts toward all-repeat_seen.
|
|
110
|
+
*/
|
|
111
|
+
maybeWarnSaturation() {
|
|
112
|
+
if (this.saturationWarned || this.bits === null)
|
|
113
|
+
return;
|
|
114
|
+
const gens = this.bits;
|
|
115
|
+
let setBits = 0;
|
|
116
|
+
for (let byte = 0; byte < this.bytesPerGen; byte++) {
|
|
117
|
+
let union = 0;
|
|
118
|
+
for (let g = 0; g < gens.length; g++) {
|
|
119
|
+
union |= gens[g][byte];
|
|
120
|
+
}
|
|
121
|
+
setBits += POPCOUNT[union];
|
|
122
|
+
}
|
|
123
|
+
const fill = setBits / this.m;
|
|
124
|
+
if (fill >= SATURATION_FILL_THRESHOLD) {
|
|
125
|
+
this.saturationWarned = true;
|
|
126
|
+
emitLog("warn", `duplicate filter is ${Math.round(fill * 100)}% full — false-positive rate is degraded and repeat_seen counts are inflated. Raise FRUGAL_DUPLICATE_CAPACITY above the number of distinct requests per window.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
rotate(nowMs) {
|
|
130
|
+
const elapsed = nowMs - this.genStartMs;
|
|
131
|
+
if (elapsed < this.rotateMs)
|
|
132
|
+
return;
|
|
133
|
+
const steps = Math.floor(elapsed / this.rotateMs);
|
|
134
|
+
const clears = Math.min(this.generations, steps);
|
|
135
|
+
for (let s = 0; s < clears; s++) {
|
|
136
|
+
this.activeIndex = (this.activeIndex + 1) % this.generations;
|
|
137
|
+
this.bits[this.activeIndex].fill(0);
|
|
138
|
+
}
|
|
139
|
+
this.genStartMs += steps * this.rotateMs;
|
|
140
|
+
}
|
|
141
|
+
positions(signature) {
|
|
142
|
+
const h1 = (parseInt(signature.slice(0, 8), 16) || 0) >>> 0;
|
|
143
|
+
const h2 = ((parseInt(signature.slice(8, 16), 16) || 0) | 1) >>> 0;
|
|
144
|
+
const out = new Array(this.k);
|
|
145
|
+
for (let i = 0; i < this.k; i++) {
|
|
146
|
+
out[i] = (h1 + i * h2) % this.m;
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
let shared = null;
|
|
152
|
+
export function getSharedDuplicateFilter(config) {
|
|
153
|
+
if (!config.duplicateDetection)
|
|
154
|
+
return null;
|
|
155
|
+
if (shared === null) {
|
|
156
|
+
shared = new RotatingBloomFilter({
|
|
157
|
+
capacity: config.duplicateCapacity,
|
|
158
|
+
fpRate: config.duplicateFpRate,
|
|
159
|
+
generations: config.duplicateGenerations,
|
|
160
|
+
windowSeconds: config.duplicateWindowSeconds,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return shared;
|
|
164
|
+
}
|
|
165
|
+
export function resetSharedDuplicateFilterForTests() {
|
|
166
|
+
shared = null;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=duplicate-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-filter.js","sourceRoot":"","sources":["../src/duplicate-filter.ts"],"names":[],"mappings":"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"}
|
package/dist/instrument.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface CallContext {
|
|
|
12
12
|
batched?: boolean;
|
|
13
13
|
/** Captured request kwargs for prompt analysis + cap utilization. */
|
|
14
14
|
requestPayload?: RequestPayload;
|
|
15
|
+
/**
|
|
16
|
+
* Optional caller-defined tag (e.g. a business unit) for the
|
|
17
|
+
* frugal.custom_label attribute. Set ONLY by
|
|
18
|
+
* the manual track API (trackAICall / startAICall) — provider wrappers must
|
|
19
|
+
* leave it unset. Values outside the config allowlist are coerced to "other".
|
|
20
|
+
*/
|
|
21
|
+
customLabel?: string;
|
|
15
22
|
}
|
|
16
23
|
export interface UsageReport {
|
|
17
24
|
responseModel?: string | null;
|
|
@@ -20,6 +27,7 @@ export interface UsageReport {
|
|
|
20
27
|
cacheReadTokens?: number | null;
|
|
21
28
|
cacheWriteTokens?: number | null;
|
|
22
29
|
reasoningTokens?: number | null;
|
|
30
|
+
agentTurns?: number | null;
|
|
23
31
|
}
|
|
24
32
|
export interface StartCallOptions {
|
|
25
33
|
/**
|
|
@@ -43,10 +51,35 @@ export declare class CallEmitter {
|
|
|
43
51
|
private finalized;
|
|
44
52
|
constructor(config: Config, ctx: CallContext, caller: CallerInfo, instruments: Instruments, startSec: number, provider: ProviderEntry, operation: string);
|
|
45
53
|
success(usage: UsageReport): void;
|
|
54
|
+
private recordCallShape;
|
|
55
|
+
private recordInternalError;
|
|
56
|
+
private recordDuplicate;
|
|
46
57
|
private recordCapUtilization;
|
|
47
58
|
private maybeAnalyze;
|
|
48
59
|
private recordStable;
|
|
49
60
|
error(err: unknown): void;
|
|
50
61
|
private baseAttrs;
|
|
51
62
|
}
|
|
63
|
+
export interface BatchRequestGroup {
|
|
64
|
+
requestModel: string;
|
|
65
|
+
count: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Record the calls a batch submission carries — one counter increment per
|
|
69
|
+
* (model, count) group so mixed-model batches attribute per model. Duration
|
|
70
|
+
* and error accounting for the submitting HTTP call stay on its CallEmitter;
|
|
71
|
+
* this only records the fanned-out request volume.
|
|
72
|
+
*/
|
|
73
|
+
export declare function recordBatchedCalls(config: Config, base: {
|
|
74
|
+
system: string;
|
|
75
|
+
operation: string;
|
|
76
|
+
}, caller: CallerInfo, groups: readonly BatchRequestGroup[]): void;
|
|
77
|
+
/**
|
|
78
|
+
* Record one batch result entry's token usage. No calls increment — the
|
|
79
|
+
* request was already counted at submission; results only attribute spend.
|
|
80
|
+
*/
|
|
81
|
+
export declare function recordBatchedUsage(config: Config, base: {
|
|
82
|
+
system: string;
|
|
83
|
+
operation: string;
|
|
84
|
+
}, caller: CallerInfo, requestModel: string, usage: UsageReport): void;
|
|
52
85
|
//# sourceMappingURL=instrument.d.ts.map
|
package/dist/instrument.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"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"}
|