@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.
Files changed (59) hide show
  1. package/README.md +73 -12
  2. package/dist/block-hash-lru.d.ts +8 -1
  3. package/dist/block-hash-lru.d.ts.map +1 -1
  4. package/dist/block-hash-lru.js +13 -4
  5. package/dist/block-hash-lru.js.map +1 -1
  6. package/dist/config.d.ts +33 -0
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +218 -27
  9. package/dist/config.js.map +1 -1
  10. package/dist/duplicate-filter.d.ts +46 -0
  11. package/dist/duplicate-filter.d.ts.map +1 -0
  12. package/dist/duplicate-filter.js +168 -0
  13. package/dist/duplicate-filter.js.map +1 -0
  14. package/dist/instrument.d.ts +33 -0
  15. package/dist/instrument.d.ts.map +1 -1
  16. package/dist/instrument.js +277 -21
  17. package/dist/instrument.js.map +1 -1
  18. package/dist/model-cap.d.ts +24 -0
  19. package/dist/model-cap.d.ts.map +1 -0
  20. package/dist/model-cap.js +72 -0
  21. package/dist/model-cap.js.map +1 -0
  22. package/dist/otel.d.ts +32 -3
  23. package/dist/otel.d.ts.map +1 -1
  24. package/dist/otel.js +203 -7
  25. package/dist/otel.js.map +1 -1
  26. package/dist/prompt-analyzer.d.ts +12 -1
  27. package/dist/prompt-analyzer.d.ts.map +1 -1
  28. package/dist/prompt-analyzer.js +185 -14
  29. package/dist/prompt-analyzer.js.map +1 -1
  30. package/dist/providers.d.ts +1 -0
  31. package/dist/providers.d.ts.map +1 -1
  32. package/dist/providers.js +4 -1
  33. package/dist/providers.js.map +1 -1
  34. package/dist/semconv.d.ts +14 -0
  35. package/dist/semconv.d.ts.map +1 -1
  36. package/dist/semconv.js +38 -2
  37. package/dist/semconv.js.map +1 -1
  38. package/dist/streams.d.ts.map +1 -1
  39. package/dist/streams.js +15 -2
  40. package/dist/streams.js.map +1 -1
  41. package/dist/track.d.ts +18 -0
  42. package/dist/track.d.ts.map +1 -1
  43. package/dist/track.js +4 -1
  44. package/dist/track.js.map +1 -1
  45. package/dist/wrappers/anthropic.d.ts.map +1 -1
  46. package/dist/wrappers/anthropic.js +9 -1
  47. package/dist/wrappers/anthropic.js.map +1 -1
  48. package/dist/wrappers/batch.d.ts +11 -0
  49. package/dist/wrappers/batch.d.ts.map +1 -0
  50. package/dist/wrappers/batch.js +338 -0
  51. package/dist/wrappers/batch.js.map +1 -0
  52. package/dist/wrappers/openai.d.ts.map +1 -1
  53. package/dist/wrappers/openai.js +37 -30
  54. package/dist/wrappers/openai.js.map +1 -1
  55. package/dist/wrappers/patching.d.ts +10 -0
  56. package/dist/wrappers/patching.d.ts.map +1 -0
  57. package/dist/wrappers/patching.js +38 -0
  58. package/dist/wrappers/patching.js.map +1 -0
  59. package/package.json +1 -1
package/dist/otel.js CHANGED
@@ -13,17 +13,37 @@ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-proto";
13
13
  import { resourceFromAttributes } from "@opentelemetry/resources";
14
14
  import { AggregationType, ConsoleMetricExporter, MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
15
15
  import { emitLog } from "./debug.js";
16
- import { FRUGAL_COMPONENT, FRUGAL_CUSTOMER_ID, FRUGAL_PROJECT_ID, METRIC_CACHE_PREFIX_STABLE, METRIC_CACHE_READ_TOKENS, METRIC_CACHE_WRITE_TOKENS, METRIC_CALLS, METRIC_ERRORS, METRIC_FEW_SHOT_COUNT, METRIC_HISTORY_DEPTH, METRIC_NOISE_RATIO, METRIC_OPERATION_DURATION, METRIC_INTERNAL_ERRORS, METRIC_OUTPUT_CAP_UTILIZATION, METRIC_REASONING_TOKENS, METRIC_STRUCTURED_OUTPUT_HINT, METRIC_TOKEN_USAGE, } from "./semconv.js";
16
+ import { FRUGAL_COMPONENT, FRUGAL_CUSTOMER_ID, FRUGAL_INSTRUMENT, FRUGAL_PROJECT_ID, METRIC_AGENT_TURNS, METRIC_CACHE_PREFIX_STABLE, METRIC_CACHE_READ_TOKENS, METRIC_CACHE_WRITE_TOKENS, METRIC_CALLS, METRIC_DUPLICATE_REQUESTS, METRIC_ERRORS, METRIC_FEW_SHOT_COUNT, METRIC_FEW_SHOT_TOKENS, METRIC_HISTORY_DEPTH, METRIC_NOISE_RATIO, METRIC_OPERATION_DURATION, METRIC_INTERNAL_ERRORS, METRIC_OUTPUT_CAP_UTILIZATION, METRIC_REASONING_TOKENS, METRIC_STRUCTURED_OUTPUT_HINT, METRIC_TOKEN_USAGE, } from "./semconv.js";
17
17
  const INSTRUMENTATION_NAME = "frugal-metrics";
18
18
  const INSTRUMENTATION_VERSION = "0.1.0";
19
+ // The attribute OTel's metrics SDK stamps on the single merged series it
20
+ // creates once an instrument exceeds its per-instrument attribute-set limit.
21
+ // Deliberately a literal here rather than an import from semconv.ts: this is
22
+ // OTel's own wire key, not a Frugal convention, and the detector below is the
23
+ // only thing that reads it.
24
+ const OTEL_METRIC_OVERFLOW = "otel.metric.overflow";
25
+ // Effective "no limit" when FRUGAL_MAX_SERIES_PER_INSTRUMENT is 0 — the OTel
26
+ // SDK has no explicit off switch, so we hand it a number no real deployment
27
+ // reaches.
28
+ export const UNLIMITED_SERIES_PER_INSTRUMENT = 1_000_000;
19
29
  let cached = null;
30
+ // A build failure is cached exactly like a success. Configuration is read from
31
+ // the environment once per process, so a build that failed will fail the same
32
+ // way every time — and every retry constructs a MeterProvider whose reader
33
+ // starts an export timer, leaking one per customer call. Remember the failure
34
+ // and rethrow it; the wrappers already catch and fall through to the real
35
+ // client call, so the customer sees a no-op SDK rather than a rebuild storm.
36
+ let buildFailure = null;
20
37
  export function getInstruments(config) {
21
38
  if (cached !== null)
22
39
  return cached;
40
+ if (buildFailure !== null)
41
+ throw buildFailure.error;
23
42
  try {
24
43
  cached = buildInstruments(config);
25
44
  }
26
45
  catch (err) {
46
+ buildFailure = { error: err };
27
47
  emitLog("error", `failed to initialize metrics: ${errorMessage(err)}`);
28
48
  throw err;
29
49
  }
@@ -36,7 +56,24 @@ function errorMessage(err) {
36
56
  }
37
57
  function buildInstruments(config) {
38
58
  const reader = buildReader(config);
39
- return buildFromReader(config, reader);
59
+ try {
60
+ return buildFromReader(config, reader);
61
+ }
62
+ catch (err) {
63
+ // The reader owns an export timer from the moment the MeterProvider
64
+ // registers it. Failing here (a bad resource, a meter that refuses an
65
+ // instrument) would otherwise strand that timer in the customer's process
66
+ // for its lifetime, exporting from a provider nobody holds a handle to.
67
+ try {
68
+ void reader.shutdown().catch(() => {
69
+ /* best effort */
70
+ });
71
+ }
72
+ catch {
73
+ /* best effort */
74
+ }
75
+ throw err;
76
+ }
40
77
  }
41
78
  export function buildFromReader(config, reader) {
42
79
  // service.name takes the customer suffix when configured, otherwise stays
@@ -77,6 +114,22 @@ export function buildFromReader(config, reader) {
77
114
  },
78
115
  },
79
116
  },
117
+ {
118
+ // Same reasoning as the operation-duration view above: OTel's default
119
+ // boundaries are tuned for durations, not integer turn counts, so a
120
+ // real agent run (typically 1–30 turns, occasionally more on long
121
+ // tool loops) would collapse into one or two buckets. These give
122
+ // visible spread across the realistic range.
123
+ instrumentName: METRIC_AGENT_TURNS,
124
+ aggregation: {
125
+ type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
126
+ options: {
127
+ boundaries: [
128
+ 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 75, 100,
129
+ ],
130
+ },
131
+ },
132
+ },
80
133
  ],
81
134
  });
82
135
  const meter = provider.getMeter(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION);
@@ -107,6 +160,10 @@ export function buildFromReader(config, reader) {
107
160
  unit: "{token}",
108
161
  description: "Reasoning / extended thinking tokens billed at output rate.",
109
162
  }),
163
+ agentTurns: meter.createHistogram(METRIC_AGENT_TURNS, {
164
+ unit: "{turn}",
165
+ description: "Model-response turns completed by an agent invocation.",
166
+ }),
110
167
  errors: meter.createCounter(METRIC_ERRORS, {
111
168
  unit: "{error}",
112
169
  description: "Count of errors raised by AI client operations.",
@@ -131,6 +188,10 @@ export function buildFromReader(config, reader) {
131
188
  unit: "{example}",
132
189
  description: "Count of consecutive user/assistant pairs preceding the final user message in single-turn calls.",
133
190
  }),
191
+ fewShotTokens: meter.createHistogram(METRIC_FEW_SHOT_TOKENS, {
192
+ unit: "{token}",
193
+ description: "Approximate token size of the few-shot example block (the user/assistant pairs counted by few_shot_count).",
194
+ }),
134
195
  noiseRatio: meter.createHistogram(METRIC_NOISE_RATIO, {
135
196
  unit: "1",
136
197
  description: "Ratio of noise characters (HTML tags, base64 runs, large whitespace) to total input characters.",
@@ -139,6 +200,10 @@ export function buildFromReader(config, reader) {
139
200
  unit: "{call}",
140
201
  description: "Count of calls whose prompt asks for structured output in prose without using tools or response_format.",
141
202
  }),
203
+ duplicateRequests: meter.createCounter(METRIC_DUPLICATE_REQUESTS, {
204
+ unit: "{call}",
205
+ description: "Per-call request-duplication state (first_seen | repeat_seen) from a time-windowed signature filter.",
206
+ }),
142
207
  };
143
208
  return applyComponentFanout(raw, config.components);
144
209
  }
@@ -148,24 +213,32 @@ export function buildFromReader(config, reader) {
148
213
  // whole project (component absent) or split by component, with no double-count
149
214
  // of the project total. internalErrors is excluded — it's a process-level
150
215
  // diagnostic, not per-component attributable.
216
+ // Every Instruments field is listed explicitly (no spread) so adding an
217
+ // instrument without deciding its fanout behavior is a compile error, not a
218
+ // silently missing per-component series.
151
219
  function applyComponentFanout(raw, components) {
152
220
  if (components.length === 0)
153
221
  return raw;
154
222
  return {
155
- ...raw,
223
+ meterProvider: raw.meterProvider,
224
+ reader: raw.reader,
156
225
  operationDuration: fanoutHistogram(raw.operationDuration, components),
157
226
  tokenUsage: fanoutHistogram(raw.tokenUsage, components),
158
227
  calls: fanoutCounter(raw.calls, components),
159
228
  cacheReadTokens: fanoutHistogram(raw.cacheReadTokens, components),
160
229
  cacheWriteTokens: fanoutHistogram(raw.cacheWriteTokens, components),
161
230
  reasoningTokens: fanoutHistogram(raw.reasoningTokens, components),
231
+ agentTurns: fanoutHistogram(raw.agentTurns, components),
162
232
  errors: fanoutCounter(raw.errors, components),
233
+ internalErrors: raw.internalErrors,
163
234
  outputCapUtilization: fanoutHistogram(raw.outputCapUtilization, components),
164
235
  cachePrefixStable: fanoutCounter(raw.cachePrefixStable, components),
165
236
  historyDepth: fanoutHistogram(raw.historyDepth, components),
166
237
  fewShotCount: fanoutHistogram(raw.fewShotCount, components),
238
+ fewShotTokens: fanoutHistogram(raw.fewShotTokens, components),
167
239
  noiseRatio: fanoutHistogram(raw.noiseRatio, components),
168
240
  structuredOutputHint: fanoutCounter(raw.structuredOutputHint, components),
241
+ duplicateRequests: fanoutCounter(raw.duplicateRequests, components),
169
242
  };
170
243
  }
171
244
  function fanoutCounter(inner, components) {
@@ -188,7 +261,7 @@ function fanoutHistogram(inner, components) {
188
261
  },
189
262
  };
190
263
  }
191
- function buildReader(config) {
264
+ export function buildReader(config) {
192
265
  const base = config.otlpEndpoint
193
266
  ? new OTLPMetricExporter({
194
267
  url: config.otlpEndpoint,
@@ -196,10 +269,75 @@ function buildReader(config) {
196
269
  })
197
270
  : new ConsoleMetricExporter();
198
271
  return new PeriodicExportingMetricReader({
199
- exporter: wrapExporterForHealth(base),
272
+ exporter: wrapExporterForHealth(base, {
273
+ projectId: config.projectId,
274
+ customerId: config.customerId,
275
+ }),
200
276
  exportIntervalMillis: config.exportIntervalMs,
277
+ // Reader-level (`default`), NOT per-View: a per-View limit applies only to
278
+ // the instruments that View matches, so any instrument added later would
279
+ // silently sit at OTel's 2000-attribute-set default and start merging
280
+ // series into `otel.metric.overflow` without anyone changing config.
281
+ cardinalityLimits: {
282
+ default: config.maxSeriesPerInstrument > 0
283
+ ? config.maxSeriesPerInstrument
284
+ : UNLIMITED_SERIES_PER_INSTRUMENT,
285
+ },
201
286
  });
202
287
  }
288
+ /**
289
+ * Walk exported metrics for data points OTel merged into its per-instrument
290
+ * overflow bucket, and return the de-duplicated, order-stable list of
291
+ * instrument names affected.
292
+ *
293
+ * Pure and total: runs on every export tick against SDK-shaped data we do not
294
+ * own, so every level is guarded and any surprise yields whatever was collected
295
+ * so far rather than an exception on the export path.
296
+ */
297
+ export function scanForOverflow(metrics) {
298
+ const found = [];
299
+ const seen = new Set();
300
+ try {
301
+ const scopeMetrics = metrics?.scopeMetrics;
302
+ if (!Array.isArray(scopeMetrics))
303
+ return found;
304
+ for (const sm of scopeMetrics) {
305
+ const list = sm?.metrics;
306
+ if (!Array.isArray(list))
307
+ continue;
308
+ for (const metric of list) {
309
+ const name = metric?.descriptor?.name;
310
+ if (typeof name !== "string" || seen.has(name))
311
+ continue;
312
+ const dataPoints = metric?.dataPoints;
313
+ if (!Array.isArray(dataPoints))
314
+ continue;
315
+ for (const dp of dataPoints) {
316
+ const attributes = dp?.attributes;
317
+ if (!attributes || typeof attributes !== "object")
318
+ continue;
319
+ if (OTEL_METRIC_OVERFLOW in attributes) {
320
+ seen.add(name);
321
+ found.push(name);
322
+ break;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ catch {
329
+ // Diagnostics must never break the export path.
330
+ }
331
+ return found;
332
+ }
333
+ /**
334
+ * The internal-errors counter, if instruments have been built. The health
335
+ * wrapper is constructed inside buildReader — before buildFromReader creates
336
+ * any instrument — so it can only resolve the counter lazily, per export.
337
+ */
338
+ function internalErrorsCounterOrNull() {
339
+ return cached === null ? null : cached.internalErrors;
340
+ }
203
341
  /**
204
342
  * Wrap an OTLP exporter so persistent export failures surface as a single
205
343
  * de-duped `error` debug callback. The periodic reader retries silently
@@ -209,11 +347,67 @@ function buildReader(config) {
209
347
  * one alert per failure run, not one per export tick.
210
348
  *
211
349
  * Delegates every other exporter method so behavior is otherwise unchanged.
350
+ *
351
+ * `identity` stamps frugal.project_id / frugal.customer_id onto the
352
+ * overflow-detection points below. Optional so tests (and any caller that only
353
+ * wants export-failure reporting) can wrap without a Config.
212
354
  */
213
- export function wrapExporterForHealth(exporter) {
355
+ export function wrapExporterForHealth(exporter, identity) {
214
356
  let consecutiveFailures = 0;
357
+ // Per-wrapper (not global) so state lives and dies with the reader it was
358
+ // built for — no reset hook to remember in tests, and two readers never share
359
+ // a "already reported" memory. Both are bounded by the instrument count, so a
360
+ // permanently overflowing instrument yields one point, not one per tick.
361
+ //
362
+ // Two sets, not one: the wrapper is built inside buildReader, BEFORE any
363
+ // instrument exists, so the very first export can find no counter to add to.
364
+ // A single "reported" set would mark the instrument done on that export and
365
+ // the internal_errors point would never be emitted, even though the counter
366
+ // exists one tick later. `logged` retires the debug line immediately (it did
367
+ // fire); `counted` is only written once the counter add actually ran.
368
+ const logged = new Set();
369
+ const counted = new Set();
215
370
  return {
216
371
  export(metrics, resultCallback) {
372
+ // Diagnostics only: never alters control flow, never recurses (the
373
+ // counter increment lands in the NEXT collection cycle), and the export
374
+ // below runs exactly as before whatever happens here.
375
+ try {
376
+ for (const name of scanForOverflow(metrics)) {
377
+ if (!logged.has(name)) {
378
+ logged.add(name);
379
+ emitLog("error", `OTel per-instrument cardinality limit exceeded on ${name}: further attribute sets are merged into a single {${OTEL_METRIC_OVERFLOW}: true} series with every other label dropped. Raise FRUGAL_MAX_SERIES_PER_INSTRUMENT, or lower FRUGAL_MAX_CALL_SITES / FRUGAL_MAX_MODELS.`, { [FRUGAL_INSTRUMENT]: name });
380
+ }
381
+ if (counted.has(name))
382
+ continue;
383
+ const counter = internalErrorsCounterOrNull();
384
+ // No counter yet — leave the name uncounted so a later export, once
385
+ // instruments exist, still lands the point.
386
+ if (counter === null)
387
+ continue;
388
+ // Identity goes on the POINT, matching cardinality_cap_hit and
389
+ // model_cap_hit: every product-side query scopes on the
390
+ // frugal.project_id point label, so relying on the resource
391
+ // attributes being flattened by OTLP ingest would drop these points
392
+ // out of every dashboard.
393
+ counter.add(1, {
394
+ ...(identity?.customerId
395
+ ? { [FRUGAL_CUSTOMER_ID]: identity.customerId }
396
+ : {}),
397
+ ...(identity?.projectId
398
+ ? { [FRUGAL_PROJECT_ID]: identity.projectId }
399
+ : {}),
400
+ "frugal.internal_error.stage": "otel_cardinality_overflow",
401
+ [FRUGAL_INSTRUMENT]: name,
402
+ });
403
+ // Only AFTER the add actually returned: a throwing counter must not
404
+ // consume the one-shot and lose the point forever.
405
+ counted.add(name);
406
+ }
407
+ }
408
+ catch {
409
+ // never let a diagnostic break the export path
410
+ }
217
411
  exporter.export(metrics, (result) => {
218
412
  if (result.code === ExportResultCode.SUCCESS) {
219
413
  if (consecutiveFailures > 0)
@@ -277,7 +471,7 @@ function parseHeaders(raw) {
277
471
  }
278
472
  return Object.keys(out).length > 0 ? out : undefined;
279
473
  }
280
- /** Test-only hook — wipe the cached instruments between tests. */
474
+ /** Test-only hook — wipe the cached instruments (and any cached failure). */
281
475
  export function resetInstrumentsForTests() {
282
476
  if (cached) {
283
477
  cached.meterProvider.shutdown().catch(() => {
@@ -285,9 +479,11 @@ export function resetInstrumentsForTests() {
285
479
  });
286
480
  }
287
481
  cached = null;
482
+ buildFailure = null;
288
483
  }
289
484
  /** Test-only hook — install pre-built instruments (e.g. with InMemory reader). */
290
485
  export function setInstrumentsForTests(instruments) {
291
486
  cached = instruments;
487
+ buildFailure = null;
292
488
  }
293
489
  //# sourceMappingURL=otel.js.map
package/dist/otel.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,2EAA2E;AAC3E,YAAY;AAGZ,yEAAyE;AACzE,4EAA4E;AAC5E,4EAA4E;AAC5E,6CAA6C;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,6BAA6B,GAI9B,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACZ,yBAAyB,EACzB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,6BAA6B,EAC7B,uBAAuB,EACvB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAEtB,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAC9C,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAExC,yEAAyE;AACzE,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;AAC9E,4BAA4B;AAC5B,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAEpD,6EAA6E;AAC7E,4EAA4E;AAC5E,WAAW;AACX,MAAM,CAAC,MAAM,+BAA+B,GAAG,SAAS,CAAC;AAmCzD,IAAI,MAAM,GAAuB,IAAI,CAAC;AACtC,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAC9E,0EAA0E;AAC1E,6EAA6E;AAC7E,IAAI,YAAY,GAA8B,IAAI,CAAC;AAEnD,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IACnC,IAAI,YAAY,KAAK,IAAI;QAAE,MAAM,YAAY,CAAC,KAAK,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAY,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC9B,OAAO,CAAC,OAAO,EAAE,iCAAiC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvE,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc;IACtC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,oEAAoE;QACpE,sEAAsE;QACtE,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,CAAC;YACH,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBAChC,iBAAiB;YACnB,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,MAAoB;IAClE,0EAA0E;IAC1E,0EAA0E;IAC1E,wEAAwE;IACxE,+BAA+B;IAC/B,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU;QACnC,CAAC,CAAC,kBAAkB,MAAM,CAAC,UAAU,EAAE;QACvC,CAAC,CAAC,gBAAgB,CAAC;IACrB,MAAM,aAAa,GAA2B;QAC5C,cAAc,EAAE,WAAW;QAC3B,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,SAAS;KACtC,CAAC;IACF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,aAAa,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC;QACjC,QAAQ;QACR,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,oEAAoE;QACpE,0EAA0E;QAC1E,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,2BAA2B;QAC3B,KAAK,EAAE;YACL;gBACE,cAAc,EAAE,yBAAyB;gBACzC,WAAW,EAAE;oBACX,IAAI,EAAE,eAAe,CAAC,yBAAyB;oBAC/C,OAAO,EAAE;wBACP,UAAU,EAAE;4BACV,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;4BAChE,EAAE;yBACH;qBACF;iBACF;aACF;YACD;gBACE,sEAAsE;gBACtE,oEAAoE;gBACpE,kEAAkE;gBAClE,iEAAiE;gBACjE,6CAA6C;gBAC7C,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE;oBACX,IAAI,EAAE,eAAe,CAAC,yBAAyB;oBAC/C,OAAO,EAAE;wBACP,UAAU,EAAE;4BACV,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG;yBAC7D;qBACF;iBACF;aACF;SACF;KACF,CAAC,CAAC;IACH,MAAM,KAAK,GAAU,QAAQ,CAAC,QAAQ,CACpC,oBAAoB,EACpB,uBAAuB,CACxB,CAAC;IACF,MAAM,GAAG,GAAgB;QACvB,aAAa,EAAE,QAAQ;QACvB,MAAM;QACN,iBAAiB,EAAE,KAAK,CAAC,eAAe,CAAC,yBAAyB,EAAE;YAClE,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,mCAAmC;SACjD,CAAC;QACF,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,kBAAkB,EAAE;YACpD,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,uCAAuC;SACrD,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE;YACvC,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,qCAAqC;SACnD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC,wBAAwB,EAAE;YAC/D,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,2CAA2C;SACzD,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,eAAe,CAAC,yBAAyB,EAAE;YACjE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,0CAA0C;SACxD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC,uBAAuB,EAAE;YAC9D,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6DAA6D;SAC3E,CAAC;QACF,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,kBAAkB,EAAE;YACpD,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,wDAAwD;SACtE,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,aAAa,EAAE;YACzC,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,iDAAiD;SAC/D,CAAC;QACF,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,EAAE;YAC1D,IAAI,EAAE,SAAS;YACf,WAAW,EACT,mEAAmE;SACtE,CAAC;QACF,oBAAoB,EAAE,KAAK,CAAC,eAAe,CAAC,6BAA6B,EAAE;YACzE,IAAI,EAAE,GAAG;YACT,WAAW,EACT,kEAAkE;SACrE,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,aAAa,CAAC,0BAA0B,EAAE;YACjE,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6GAA6G;SAChH,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC,oBAAoB,EAAE;YACxD,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,4CAA4C;SAC1D,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC,qBAAqB,EAAE;YACzD,IAAI,EAAE,WAAW;YACjB,WAAW,EACT,kGAAkG;SACrG,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,eAAe,CAAC,sBAAsB,EAAE;YAC3D,IAAI,EAAE,SAAS;YACf,WAAW,EACT,4GAA4G;SAC/G,CAAC;QACF,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,kBAAkB,EAAE;YACpD,IAAI,EAAE,GAAG;YACT,WAAW,EACT,iGAAiG;SACpG,CAAC;QACF,oBAAoB,EAAE,KAAK,CAAC,aAAa,CAAC,6BAA6B,EAAE;YACvE,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,yGAAyG;SAC5G,CAAC;QACF,iBAAiB,EAAE,KAAK,CAAC,aAAa,CAAC,yBAAyB,EAAE;YAChE,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,sGAAsG;SACzG,CAAC;KACH,CAAC;IACF,OAAO,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC;AAED,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,+EAA+E;AAC/E,0EAA0E;AAC1E,8CAA8C;AAC9C,wEAAwE;AACxE,4EAA4E;AAC5E,yCAAyC;AACzC,SAAS,oBAAoB,CAAC,GAAgB,EAAE,UAA6B;IAC3E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACxC,OAAO;QACL,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,iBAAiB,EAAE,eAAe,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;QACrE,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC;QACvD,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC;QAC3C,eAAe,EAAE,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC;QACjE,gBAAgB,EAAE,eAAe,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC;QACnE,eAAe,EAAE,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC;QACjE,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC;QACvD,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;QAC7C,cAAc,EAAE,GAAG,CAAC,cAAc;QAClC,oBAAoB,EAAE,eAAe,CAAC,GAAG,CAAC,oBAAoB,EAAE,UAAU,CAAC;QAC3E,iBAAiB,EAAE,aAAa,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;QACnE,YAAY,EAAE,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC;QAC3D,YAAY,EAAE,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC;QAC3D,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC;QAC7D,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC;QACvD,oBAAoB,EAAE,aAAa,CAAC,GAAG,CAAC,oBAAoB,EAAE,UAAU,CAAC;QACzE,iBAAiB,EAAE,aAAa,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC;KACpE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc,EAAE,UAA6B;IAClE,OAAO;QACL,GAAG,CAAC,KAAa,EAAE,UAAuB,EAAE,OAAiB;YAC3D,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YACtC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAgB,EAAE,UAA6B;IACtE,OAAO;QACL,MAAM,CAAC,KAAa,EAAE,UAAuB,EAAE,OAAiB;YAC9D,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YACzC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,IAAI,GAAuB,MAAM,CAAC,YAAY;QAClD,CAAC,CAAC,IAAI,kBAAkB,CAAC;YACrB,GAAG,EAAE,MAAM,CAAC,YAAY;YACxB,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC;SAC1C,CAAC;QACJ,CAAC,CAAC,IAAI,qBAAqB,EAAE,CAAC;IAChC,OAAO,IAAI,6BAA6B,CAAC;QACvC,QAAQ,EAAE,qBAAqB,CAAC,IAAI,EAAE;YACpC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;QACF,oBAAoB,EAAE,MAAM,CAAC,gBAAgB;QAC7C,2EAA2E;QAC3E,yEAAyE;QACzE,sEAAsE;QACtE,qEAAqE;QACrE,iBAAiB,EAAE;YACjB,OAAO,EACL,MAAM,CAAC,sBAAsB,GAAG,CAAC;gBAC/B,CAAC,CAAC,MAAM,CAAC,sBAAsB;gBAC/B,CAAC,CAAC,+BAA+B;SACtC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,EAAE,EAAE,OAAO,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,SAAS;YACnC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAG,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC;gBACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACzD,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,CAAC;gBACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;oBAAE,SAAS;gBACzC,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;oBAC5B,MAAM,UAAU,GAAG,EAAE,EAAE,UAAU,CAAC;oBAClC,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;wBAAE,SAAS;oBAC5D,IAAI,oBAAoB,IAAI,UAAU,EAAE,CAAC;wBACvC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;wBACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACjB,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,2BAA2B;IAClC,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;AACxD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAA4B,EAC5B,QAA2B;IAE3B,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,0EAA0E;IAC1E,8EAA8E;IAC9E,8EAA8E;IAC9E,yEAAyE;IACzE,EAAE;IACF,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,sEAAsE;IACtE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,OAAO;QACL,MAAM,CAAC,OAAO,EAAE,cAAc;YAC5B,mEAAmE;YACnE,wEAAwE;YACxE,sDAAsD;YACtD,IAAI,CAAC;gBACH,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC5C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;wBACtB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;wBACjB,OAAO,CACL,OAAO,EACP,qDAAqD,IAAI,sDAAsD,oBAAoB,4IAA4I,EAC/Q,EAAE,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAC9B,CAAC;oBACJ,CAAC;oBACD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;wBAAE,SAAS;oBAChC,MAAM,OAAO,GAAG,2BAA2B,EAAE,CAAC;oBAC9C,oEAAoE;oBACpE,4CAA4C;oBAC5C,IAAI,OAAO,KAAK,IAAI;wBAAE,SAAS;oBAC/B,+DAA+D;oBAC/D,wDAAwD;oBACxD,4DAA4D;oBAC5D,oEAAoE;oBACpE,0BAA0B;oBAC1B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE;wBACb,GAAG,CAAC,QAAQ,EAAE,UAAU;4BACtB,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,UAAU,EAAE;4BAC/C,CAAC,CAAC,EAAE,CAAC;wBACP,GAAG,CAAC,QAAQ,EAAE,SAAS;4BACrB,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,SAAS,EAAE;4BAC7C,CAAC,CAAC,EAAE,CAAC;wBACP,6BAA6B,EAAE,2BAA2B;wBAC1D,CAAC,iBAAiB,CAAC,EAAE,IAAI;qBAC1B,CAAC,CAAC;oBACH,oEAAoE;oBACpE,mDAAmD;oBACnD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,+CAA+C;YACjD,CAAC;YACD,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;gBAClC,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBAC7C,IAAI,mBAAmB,GAAG,CAAC;wBAAE,mBAAmB,GAAG,CAAC,CAAC;gBACvD,CAAC;qBAAM,CAAC;oBACN,mBAAmB,IAAI,CAAC,CAAC;oBACzB,IAAI,mBAAmB,KAAK,CAAC,EAAE,CAAC;wBAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;wBACrE,OAAO,CAAC,OAAO,EAAE,0BAA0B,MAAM,EAAE,EAAE;4BACnD,qBAAqB,EAAE,MAAM;yBAC9B,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBACD,cAAc,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,UAAU;YACR,OAAO,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC/B,CAAC;QACD,QAAQ;YACN,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC;QACD,4BAA4B,EAAE,QAAQ,CAAC,4BAA4B;YACjE,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CACjB,QAAQ,CAAC,4BAA6B,CAAC,cAAc,CAAC;YAC1D,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC5B,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC;IACtC,MAAM,GAAG,IAAI,CAAC;IACd,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,YAAY,CAAC,GAAkB;IACtC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACrB,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,wBAAwB;IACtC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;YACzC,YAAY;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,GAAG,IAAI,CAAC;IACd,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,sBAAsB,CAAC,WAAwB;IAC7D,MAAM,GAAG,WAAW,CAAC;IACrB,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { type HistoryBucket } from "./semconv.js";
1
2
  export interface RequestPayload {
2
3
  /** Provider-specific messages array (OpenAI chat / Anthropic messages). */
3
4
  messages?: unknown;
@@ -9,18 +10,28 @@ export interface RequestPayload {
9
10
  maxTokens?: number | null;
10
11
  /** Optional system prompt for Anthropic (passed alongside messages). */
11
12
  system?: unknown;
13
+ /**
14
+ * OpenAI Responses API previous_response_id. Stateful conversations carry
15
+ * server-side history the signature can't see, so this is folded into the
16
+ * duplicate signature to keep short recurring turns ("continue") from
17
+ * colliding across genuinely distinct conversations.
18
+ */
19
+ previousResponseId?: string | null;
12
20
  }
13
21
  export interface AnalysisResult {
14
22
  systemHash: string | null;
15
23
  userHash: string | null;
16
24
  toolsHash: string | null;
17
25
  schemaHash: string | null;
18
- historyDepth: number | null;
19
26
  fewShotCount: number | null;
27
+ fewShotTokens: number | null;
20
28
  noiseRatio: number | null;
21
29
  structuredOutputHint: boolean;
22
30
  }
23
31
  export declare function analyzeRequest(payload: RequestPayload): AnalysisResult;
24
32
  export declare function structuredOutputMode(payload: RequestPayload): string;
33
+ export declare function historyDepth(payload: RequestPayload): number | null;
34
+ export declare function historyBucket(n: number): HistoryBucket;
35
+ export declare function requestSignature(payload: RequestPayload, model: string, callSiteId: string): string | null;
25
36
  export declare function shouldSample(callSiteId: string, sampleRate: number, nowMs?: number): boolean;
26
37
  //# sourceMappingURL=prompt-analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-analyzer.d.ts","sourceRoot":"","sources":["../src/prompt-analyzer.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CActE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAWpE;AAyKD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAmB,GACzB,OAAO,CAYT"}
1
+ {"version":3,"file":"prompt-analyzer.d.ts","sourceRoot":"","sources":["../src/prompt-analyzer.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CActE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAWpE;AA2JD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAGnE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAQtD;AA0HD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CA8Bf;AA6BD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAmB,GACzB,OAAO,CAYT"}
@@ -11,8 +11,8 @@ export function analyzeRequest(payload) {
11
11
  userHash: safe(() => hashUserBlock(payload), null),
12
12
  toolsHash: safe(() => hashJSON(payload.tools), null),
13
13
  schemaHash: safe(() => hashJSON(payload.responseFormat), null),
14
- historyDepth: safe(() => historyDepth(payload), null),
15
14
  fewShotCount: safe(() => fewShotCount(payload), null),
15
+ fewShotTokens: safe(() => fewShotTokens(payload), null),
16
16
  noiseRatio: safe(() => noiseRatio(payload), null),
17
17
  structuredOutputHint: safe(() => structuredOutputHint(payload), false),
18
18
  };
@@ -49,14 +49,98 @@ function hashJSON(value) {
49
49
  return sha256(canonicalize(value));
50
50
  }
51
51
  function canonicalize(value) {
52
- if (value === null || typeof value !== "object")
53
- return JSON.stringify(value);
54
- if (Array.isArray(value)) {
55
- return "[" + value.map((v) => canonicalize(v)).join(",") + "]";
52
+ const parts = [];
53
+ streamCanonical(value, (chunk) => parts.push(chunk));
54
+ return parts.join("");
55
+ }
56
+ // Canonical-JSON serialization pushed through a sink chunk by chunk, so the
57
+ // signature path can hash incrementally under a byte budget instead of
58
+ // materializing one giant string. Normalized to JSON wire semantics: an
59
+ // explicitly-undefined property serializes identically to an omitted one, so
60
+ // SDK-built objects with optional undefined props can't evade duplicate
61
+ // detection. Binary content (TypedArray / ArrayBuffer — e.g. Bedrock Converse
62
+ // images) contributes only its byteLength, never its bytes: hashing megabytes
63
+ // of image data per call buys no duplicate signal worth its CPU cost, and the
64
+ // generic object branch would sort one key per byte.
65
+ //
66
+ // This walk runs on 100% of chat calls, so every input dimension is bounded,
67
+ // not just the total output (the sink's byte budget checks a chunk only after
68
+ // it exists):
69
+ // - String leaves are capped at MAX_STRING_LEAF_CHARS before stringification.
70
+ // Base64 images arrive as plain strings (OpenAI `image_url.url`, Anthropic
71
+ // `source.data`) — stringifying a multi-MB data URL whole would allocate a
72
+ // same-sized escaped copy per call. The leaf contributes its head plus its
73
+ // total length, so strings identical through the cap but of different
74
+ // lengths still differ; same-length strings differing only past the cap
75
+ // collide — the same trade-off as the binary byteLength branch.
76
+ // - Recursion is depth-capped (everything below MAX_CANONICAL_DEPTH collapses
77
+ // to one marker) — the byte budget bounds breadth but not depth, and a
78
+ // pathologically nested payload would exhaust the JS stack first.
79
+ // - Ancestor cycles emit a marker instead of recursing forever. The guard is
80
+ // path-scoped (added on entry, removed on exit), so a shared sub-object
81
+ // appearing twice (a DAG) still serializes both times.
82
+ const MAX_STRING_LEAF_CHARS = 8 * 1024;
83
+ const MAX_CANONICAL_DEPTH = 64;
84
+ function streamCanonical(value, sink) {
85
+ walkCanonical(value, sink, 0, new WeakSet());
86
+ }
87
+ function walkCanonical(value, sink, depth, ancestors) {
88
+ if (typeof value === "string" && value.length > MAX_STRING_LEAF_CHARS) {
89
+ sink(JSON.stringify(`${value.slice(0, MAX_STRING_LEAF_CHARS)}<str:${value.length}>`));
90
+ return;
91
+ }
92
+ if (value === null || typeof value !== "object") {
93
+ // JSON.stringify yields undefined for undefined/function/symbol — all
94
+ // serialize as null on the wire.
95
+ sink(JSON.stringify(value) ?? "null");
96
+ return;
97
+ }
98
+ if (ArrayBuffer.isView(value)) {
99
+ sink(`"<binary:${value.byteLength}>"`);
100
+ return;
101
+ }
102
+ if (value instanceof ArrayBuffer) {
103
+ sink(`"<binary:${value.byteLength}>"`);
104
+ return;
105
+ }
106
+ if (depth >= MAX_CANONICAL_DEPTH) {
107
+ sink('"<maxdepth>"');
108
+ return;
109
+ }
110
+ if (ancestors.has(value)) {
111
+ sink('"<cycle>"');
112
+ return;
113
+ }
114
+ ancestors.add(value);
115
+ try {
116
+ if (Array.isArray(value)) {
117
+ sink("[");
118
+ for (let i = 0; i < value.length; i++) {
119
+ if (i > 0)
120
+ sink(",");
121
+ walkCanonical(value[i], sink, depth + 1, ancestors);
122
+ }
123
+ sink("]");
124
+ return;
125
+ }
126
+ const obj = value;
127
+ const keys = Object.keys(obj)
128
+ .filter((k) => obj[k] !== undefined)
129
+ .sort();
130
+ sink("{");
131
+ for (let i = 0; i < keys.length; i++) {
132
+ if (i > 0)
133
+ sink(",");
134
+ sink(JSON.stringify(keys[i]) + ":");
135
+ walkCanonical(obj[keys[i]], sink, depth + 1, ancestors);
136
+ }
137
+ sink("}");
138
+ }
139
+ finally {
140
+ // finally, not post-loop: the budget sink aborts the walk by throwing, and
141
+ // the ancestor set must unwind with the stack either way.
142
+ ancestors.delete(value);
56
143
  }
57
- const keys = Object.keys(value).sort();
58
- const parts = keys.map((k) => JSON.stringify(k) + ":" + canonicalize(value[k]));
59
- return "{" + parts.join(",") + "}";
60
144
  }
61
145
  function hashSystemBlock(payload) {
62
146
  const blocks = [];
@@ -88,12 +172,27 @@ function hashUserBlock(payload) {
88
172
  return hashJSON(blocks);
89
173
  }
90
174
  // --- structural counts -----------------------------------------------------
91
- function historyDepth(payload) {
175
+ export function historyDepth(payload) {
92
176
  if (!Array.isArray(payload.messages))
93
177
  return null;
94
178
  return payload.messages.length;
95
179
  }
96
- function fewShotCount(payload) {
180
+ export function historyBucket(n) {
181
+ if (n <= 0)
182
+ return "0";
183
+ if (n <= 2)
184
+ return "1-2";
185
+ if (n <= 5)
186
+ return "3-5";
187
+ if (n <= 10)
188
+ return "6-10";
189
+ if (n <= 20)
190
+ return "11-20";
191
+ if (n <= 50)
192
+ return "21-50";
193
+ return "51+";
194
+ }
195
+ function fewShotSpan(payload) {
97
196
  if (!Array.isArray(payload.messages))
98
197
  return null;
99
198
  const msgs = payload.messages.filter((m) => m !== null && typeof m === "object");
@@ -113,20 +212,51 @@ function fewShotCount(payload) {
113
212
  if (Array.isArray(m.tool_calls) && m.tool_calls.length > 0)
114
213
  return null;
115
214
  }
116
- // Count consecutive (user, assistant) pairs preceding the final user.
117
- let pairs = 0;
215
+ // Collect consecutive (user, assistant) pairs preceding the final user.
216
+ const exampleMessages = [];
118
217
  let j = i;
119
218
  const lastIdx = msgs.length - 1; // final user
120
219
  while (j + 1 < lastIdx) {
121
220
  if (msgs[j].role === "user" && msgs[j + 1].role === "assistant") {
122
- pairs++;
221
+ exampleMessages.push(msgs[j], msgs[j + 1]);
123
222
  j += 2;
124
223
  }
125
224
  else {
126
225
  break;
127
226
  }
128
227
  }
129
- return pairs;
228
+ return { pairs: exampleMessages.length / 2, exampleMessages };
229
+ }
230
+ function fewShotCount(payload) {
231
+ const span = fewShotSpan(payload);
232
+ return span === null ? null : span.pairs;
233
+ }
234
+ function fewShotTokens(payload) {
235
+ const span = fewShotSpan(payload);
236
+ if (span === null)
237
+ return null;
238
+ return estimateTokens(messagesText(span.exampleMessages));
239
+ }
240
+ function estimateTokens(text) {
241
+ return Math.ceil(text.length / 4);
242
+ }
243
+ function messagesText(messages) {
244
+ const parts = [];
245
+ for (const m of messages) {
246
+ const content = m.content;
247
+ if (typeof content === "string")
248
+ parts.push(content);
249
+ else if (Array.isArray(content)) {
250
+ for (const c of content) {
251
+ if (!c || typeof c !== "object")
252
+ continue;
253
+ const text = c.text;
254
+ if (typeof text === "string")
255
+ parts.push(text);
256
+ }
257
+ }
258
+ }
259
+ return parts.join("\n");
130
260
  }
131
261
  // --- noise ratio -----------------------------------------------------------
132
262
  const HTML_TAG_REGEX = /<[^>]+>/g;
@@ -170,6 +300,47 @@ function collectText(payload) {
170
300
  }
171
301
  return parts.join("\n");
172
302
  }
303
+ // The signature runs on 100% of chat calls, synchronously on the caller's hot
304
+ // path, so its cost must stay bounded regardless of payload size. Hashing is
305
+ // incremental (no giant intermediate string) and capped: past
306
+ // SIGNATURE_MAX_CHARS canonical characters, traversal stops and a truncation
307
+ // marker plus the message count is folded in instead. Multi-MB payloads
308
+ // identical in their first 256K canonical chars therefore collide — an
309
+ // accepted trade-off; the alternative is serializing megabytes per call.
310
+ const SIGNATURE_MAX_CHARS = 256 * 1024;
311
+ const TRUNCATED = Symbol("frugal.signature.truncated");
312
+ export function requestSignature(payload, model, callSiteId) {
313
+ if (!Array.isArray(payload.messages))
314
+ return null;
315
+ const hash = createHash("sha256");
316
+ let remaining = SIGNATURE_MAX_CHARS;
317
+ const sink = (chunk) => {
318
+ remaining -= chunk.length;
319
+ if (remaining < 0)
320
+ throw TRUNCATED;
321
+ hash.update(chunk);
322
+ };
323
+ try {
324
+ streamCanonical({
325
+ site: callSiteId,
326
+ model,
327
+ system: payload.system ?? null,
328
+ messages: payload.messages,
329
+ tools: payload.tools ?? null,
330
+ responseFormat: payload.responseFormat ?? null,
331
+ maxTokens: payload.maxTokens ?? null,
332
+ ...(payload.previousResponseId
333
+ ? { previousResponseId: payload.previousResponseId }
334
+ : {}),
335
+ }, sink);
336
+ }
337
+ catch (err) {
338
+ if (err !== TRUNCATED)
339
+ throw err;
340
+ hash.update(`|truncated|messages:${payload.messages.length}`);
341
+ }
342
+ return hash.digest("hex");
343
+ }
173
344
  // --- structured output hint ------------------------------------------------
174
345
  const STRUCTURED_HINT_REGEXES = [
175
346
  /format\s+as\s+JSON/i,