@kortyx/usage-telemetry 0.0.0-stage → 0.2.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.
@@ -0,0 +1,676 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/browser-node.ts
21
+ var browser_node_exports = {};
22
+ __export(browser_node_exports, {
23
+ configureUsageTelemetry: () => configureUsageTelemetry,
24
+ createNodeUsageTelemetry: () => createNodeUsageTelemetry,
25
+ createUsageTelemetry: () => createUsageTelemetry,
26
+ getUsageTelemetry: () => getUsageTelemetry,
27
+ publicUsageConfiguration: () => publicUsageConfiguration,
28
+ scale: () => scale,
29
+ usageDisabled: () => usageDisabled
30
+ });
31
+ module.exports = __toCommonJS(browser_node_exports);
32
+
33
+ // src/catalog.ts
34
+ var operations = [
35
+ "sdk.initialize",
36
+ "sdk.registry",
37
+ "sdk.execute",
38
+ "sdk.resume",
39
+ "sdk.chat.admission",
40
+ "sdk.execution",
41
+ "sdk.response",
42
+ "sdk.model",
43
+ "sdk.tool",
44
+ "sdk.node",
45
+ "sdk.parallel",
46
+ "sdk.child",
47
+ "sdk.structured",
48
+ "sdk.complete_response",
49
+ "sdk.prompt.resolve",
50
+ "sdk.prompt.refresh",
51
+ "sdk.eval",
52
+ "sdk.mcp.connect",
53
+ "sdk.mcp.discover",
54
+ "sdk.mcp.close",
55
+ "sdk.checkpoint.read",
56
+ "sdk.checkpoint.list",
57
+ "sdk.checkpoint.fork",
58
+ "sdk.checkpoint.rollback",
59
+ "sdk.export",
60
+ "studio.setup",
61
+ "studio.connection",
62
+ "studio.read",
63
+ "studio.render",
64
+ "studio.navigation",
65
+ "studio.inspect",
66
+ "studio.filter",
67
+ "studio.saved_view",
68
+ "studio.live",
69
+ "studio.prompt",
70
+ "studio.eval",
71
+ "studio.review",
72
+ "studio.settings",
73
+ "studio.update",
74
+ "studio.ingest",
75
+ "cli.topology",
76
+ "cli.eval"
77
+ ];
78
+ var outcomes = [
79
+ "success",
80
+ "failed",
81
+ "cancelled",
82
+ "suspended",
83
+ "denied",
84
+ "limit_reached",
85
+ "quality_failed",
86
+ "ungraded"
87
+ ];
88
+ var publicCatalog = {
89
+ products: ["sdk", "oss_studio"],
90
+ operations,
91
+ properties: {
92
+ phase: [
93
+ "admission",
94
+ "execution",
95
+ "delivery",
96
+ "parse",
97
+ "network",
98
+ "http",
99
+ "configuration",
100
+ "preflight",
101
+ "state",
102
+ "pull",
103
+ "ports",
104
+ "compose",
105
+ "rollback",
106
+ "backup",
107
+ "migration",
108
+ "health"
109
+ ],
110
+ source: [
111
+ "memory",
112
+ "file",
113
+ "custom",
114
+ "local",
115
+ "studio",
116
+ "cache",
117
+ "fallback",
118
+ "eval",
119
+ "mcp",
120
+ "native"
121
+ ],
122
+ storage: ["in-memory", "redis", "postgres", "custom"],
123
+ calling_mode: ["direct", "model"],
124
+ provider: [
125
+ "openai",
126
+ "anthropic",
127
+ "google",
128
+ "mistral",
129
+ "groq",
130
+ "deepseek",
131
+ "openrouter"
132
+ ],
133
+ transport: ["stdio", "sse", "http", "custom"],
134
+ format: [
135
+ "text",
136
+ "json",
137
+ "json_schema",
138
+ "set",
139
+ "append",
140
+ "text-delta",
141
+ "final"
142
+ ],
143
+ resource: [
144
+ "runs",
145
+ "sessions",
146
+ "interrupts",
147
+ "workflows",
148
+ "prompts",
149
+ "evals",
150
+ "diagnostics",
151
+ "settings",
152
+ "home"
153
+ ],
154
+ surface: [
155
+ "runs",
156
+ "sessions",
157
+ "interrupts",
158
+ "workflows",
159
+ "prompts",
160
+ "evals",
161
+ "settings",
162
+ "other"
163
+ ],
164
+ action: [
165
+ "view",
166
+ "select",
167
+ "retry",
168
+ "first_use",
169
+ "observed",
170
+ "copy",
171
+ "create",
172
+ "draft",
173
+ "save",
174
+ "discard-draft",
175
+ "update",
176
+ "promote",
177
+ "review",
178
+ "policy",
179
+ "tag-set",
180
+ "tag-remove",
181
+ "bulk-update",
182
+ "category-create",
183
+ "category-update",
184
+ "category-delete",
185
+ "group-create",
186
+ "group-update",
187
+ "group-delete",
188
+ "import",
189
+ "export",
190
+ "launch",
191
+ "cancel",
192
+ "compare",
193
+ "inspect",
194
+ "clear",
195
+ "apply",
196
+ "delete",
197
+ "enable",
198
+ "disable",
199
+ "manual_refresh",
200
+ "fallback_refresh",
201
+ "refresh",
202
+ "change"
203
+ ],
204
+ tab: [
205
+ "overview",
206
+ "trace",
207
+ "events",
208
+ "model-io",
209
+ "calls",
210
+ "feedback",
211
+ "content",
212
+ "versions",
213
+ "reviews",
214
+ "usage",
215
+ "diff",
216
+ "cases",
217
+ "results",
218
+ "definition"
219
+ ],
220
+ origin: ["foreground", "background", "server", "browser", "cli"],
221
+ status: [
222
+ "empty",
223
+ "nonempty",
224
+ "off",
225
+ "connecting",
226
+ "live",
227
+ "reconnecting",
228
+ "paused",
229
+ "running",
230
+ "completed",
231
+ "failed",
232
+ "interrupted",
233
+ "pending",
234
+ "expired"
235
+ ],
236
+ filter: [
237
+ "search",
238
+ "status",
239
+ "provider",
240
+ "model",
241
+ "environment",
242
+ "version",
243
+ "duration",
244
+ "cost",
245
+ "tokens",
246
+ "time",
247
+ "sort",
248
+ "other"
249
+ ],
250
+ scale: ["1", "2-5", "6-20", "21-100", "101+"],
251
+ error_category: [
252
+ "configuration",
253
+ "provider",
254
+ "validation",
255
+ "domain",
256
+ "workflow",
257
+ "persistence",
258
+ "request",
259
+ "transport",
260
+ "internal",
261
+ "unknown"
262
+ ],
263
+ http_status: [
264
+ "400",
265
+ "401",
266
+ "403",
267
+ "404",
268
+ "409",
269
+ "413",
270
+ "422",
271
+ "429",
272
+ "500",
273
+ "502",
274
+ "503",
275
+ "504"
276
+ ],
277
+ prompts: "boolean",
278
+ observability: "boolean",
279
+ tools: "boolean",
280
+ streaming: "boolean",
281
+ requested_streaming: "boolean",
282
+ executed: "boolean",
283
+ cache: "boolean",
284
+ reused: "boolean",
285
+ continue_on_disconnect: "boolean",
286
+ write_available: "boolean"
287
+ },
288
+ // Built-in contracts only; application codes and provider response text are excluded.
289
+ errorCodes: [
290
+ "EXECUTION_FAILED",
291
+ "INVALID_REQUEST",
292
+ "INVALID_RESUME",
293
+ "INVALID_RESPONSE",
294
+ "INVALID_SESSION",
295
+ "RESUME_MISMATCH",
296
+ "RESUME_FAILED",
297
+ "CONTRACT_MISMATCH",
298
+ "INVALID_INPUT",
299
+ "INVALID_OUTPUT",
300
+ "MISSING_CONTRACT",
301
+ "UNKNOWN_WORKFLOW",
302
+ "DOMAIN_ERROR",
303
+ "PERSISTENCE_ERROR",
304
+ "WORKFLOW_CONTRACT_ERROR",
305
+ "PROVIDER_REFUSAL",
306
+ "PROVIDER_HTTP_ERROR",
307
+ "PROVIDER_INVALID_RESPONSE",
308
+ "PROVIDER_TRANSPORT_ERROR",
309
+ "PROVIDER_REQUEST_FAILED",
310
+ "INVALID_MODEL_JSON",
311
+ "MODEL_OUTPUT_SCHEMA",
312
+ "OUTPUT_TRUNCATED",
313
+ "SCHEMA_VALIDATION",
314
+ "PARALLEL_FAILED",
315
+ "EVAL_TIMEOUT",
316
+ "EVAL_HOOK_FAILED",
317
+ "EVAL_INTERRUPT_CLEANUP_FAILED",
318
+ "PROMPT_SOURCE_NOT_CONFIGURED",
319
+ "PROMPT_REASON_CONFLICT",
320
+ "PROMPT_REASON_INVALID",
321
+ "REASON_OUTPUT_BUDGET_EXHAUSTED",
322
+ "REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
323
+ "PROMPT_CACHE_INVALID",
324
+ "PROMPT_ENVIRONMENT_MISMATCH",
325
+ "PROMPT_EVAL_PIN_CONFLICT",
326
+ "PROMPT_EVAL_SNAPSHOT_INVALID",
327
+ "PROMPT_NOT_ASSIGNED",
328
+ "PROMPT_NOT_FOUND",
329
+ "PROMPT_NOT_REGISTERED",
330
+ "PROMPT_PIN_MISMATCH",
331
+ "PROMPT_REFERENCE_DUPLICATE",
332
+ "PROMPT_SNAPSHOT_INVALID",
333
+ "PROMPT_SNAPSHOT_LIMIT",
334
+ "PROMPT_SOURCE_HTTP",
335
+ "PROMPT_SOURCE_INVALID",
336
+ "PROMPT_TAG_MISMATCH",
337
+ "PROMPT_CONTRACT_MISMATCH",
338
+ "PROMPT_REFERENCE_INVALID",
339
+ "PROMPT_SCHEMA_INVALID",
340
+ "PROMPT_VARIABLE_CONFIG_OVERLAP",
341
+ "PROMPT_VARIABLE_MISSING",
342
+ "PROMPT_VARIABLE_UNKNOWN",
343
+ "PROMPT_DEPENDENCY_CYCLE",
344
+ "PROMPT_DEPENDENCY_MISMATCH",
345
+ "PROMPT_HASH_MISMATCH",
346
+ "PROMPT_REFERENCE_LIMIT",
347
+ "PROMPT_REFERENCE_MISSING",
348
+ "PROMPT_REFERENCE_ROLE",
349
+ "STUDIO_PROTOCOL_MISMATCH"
350
+ ]
351
+ };
352
+ function scale(value) {
353
+ return value <= 1 ? "1" : value <= 5 ? "2-5" : value <= 20 ? "6-20" : value <= 100 ? "21-100" : "101+";
354
+ }
355
+
356
+ // src/client.ts
357
+ function property(value, key) {
358
+ try {
359
+ if (!value || typeof value !== "object") return void 0;
360
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
361
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
362
+ } catch {
363
+ return void 0;
364
+ }
365
+ }
366
+ function classifyUsageError(error, catalog = publicCatalog) {
367
+ const name = property(error, "name");
368
+ const code = property(error, "code") ?? property(property(error, "failure"), "code");
369
+ if (name === "AbortError" || code === "EXECUTION_CANCELLED")
370
+ return { outcome: "cancelled", properties: {} };
371
+ if (code === "EXECUTION_LIMIT_REACHED" || name === "ExecutionLimitReached")
372
+ return { outcome: "limit_reached", properties: {} };
373
+ if (name === "GraphInterrupt" || name === "NodeInterrupt" || name === "Interrupt")
374
+ return { outcome: "suspended", properties: {} };
375
+ const known = typeof code === "string" && catalog.errorCodes.includes(code);
376
+ const category = known && code !== "EXECUTION_FAILED" ? property(error, "category") ?? property(property(error, "failure"), "category") ?? "unknown" : "unknown";
377
+ const status = property(error, "status") ?? property(property(error, "failure"), "status");
378
+ return {
379
+ outcome: "failed",
380
+ properties: {
381
+ error_code: known ? code : "other",
382
+ error_category: category,
383
+ ...typeof status === "number" ? { http_status: String(status) } : {}
384
+ }
385
+ };
386
+ }
387
+ function sanitizeProperties(input, catalog = publicCatalog) {
388
+ const safe = {};
389
+ for (const [key, rule] of Object.entries(catalog.properties)) {
390
+ const value = property(input, key);
391
+ if (value === void 0) continue;
392
+ if (rule === "boolean") {
393
+ if (typeof value === "boolean") safe[key] = value;
394
+ } else if (typeof value === "string")
395
+ safe[key] = rule.includes(value) ? value : "other";
396
+ }
397
+ const code = property(input, "error_code");
398
+ if (typeof code === "string")
399
+ safe.error_code = catalog.errorCodes.includes(code) ? code : "other";
400
+ return safe;
401
+ }
402
+ var durationBounds = [10, 100, 1e3, 1e4, 6e4];
403
+ var noopOperation = { end() {
404
+ }, fail() {
405
+ } };
406
+ function schedule(callback, ms) {
407
+ const timer = setTimeout(callback, ms);
408
+ timer.unref?.();
409
+ return { cancel: () => clearTimeout(timer) };
410
+ }
411
+ function createUsageTelemetry(options) {
412
+ const catalog = options.catalog ?? publicCatalog;
413
+ const now = options.now ?? Date.now;
414
+ const pending = /* @__PURE__ */ new Map();
415
+ let timer;
416
+ let flight;
417
+ let disposed = false;
418
+ let dropped = 0;
419
+ let delivered = 0;
420
+ let hour = Math.floor(now() / 36e5);
421
+ let sent = 0;
422
+ const active = () => {
423
+ try {
424
+ return !disposed && (options.enabled?.() ?? true);
425
+ } catch {
426
+ return false;
427
+ }
428
+ };
429
+ const clear = () => {
430
+ pending.clear();
431
+ try {
432
+ timer?.cancel();
433
+ } catch {
434
+ }
435
+ timer = void 0;
436
+ };
437
+ const configured = catalog.products.includes(options.context.product) && /^[a-z][a-z0-9_]{0,31}$/.test(options.context.component) && /^(?:\d+\.\d+\.\d+(?:-[a-z0-9.-]+)?|development|unknown)$/.test(
438
+ options.context.version
439
+ ) && options.context.version.length <= 64;
440
+ const flush = async () => {
441
+ if (flight) return flight;
442
+ if (!active() || !configured) {
443
+ clear();
444
+ return;
445
+ }
446
+ try {
447
+ timer?.cancel();
448
+ } catch {
449
+ }
450
+ timer = void 0;
451
+ const records = [...pending.values()];
452
+ pending.clear();
453
+ if (!records.length) return;
454
+ let attempted = records.length;
455
+ flight = (async () => {
456
+ try {
457
+ if (options.debug?.()) {
458
+ options.inspect?.(records);
459
+ return;
460
+ }
461
+ const currentHour = Math.floor(now() / 36e5);
462
+ if (hour !== currentHour) {
463
+ hour = currentHour;
464
+ sent = 0;
465
+ }
466
+ const allowance = Math.max(
467
+ 0,
468
+ (options.maxRecordsPerHour ?? 120) - sent
469
+ );
470
+ const batch = records.slice(0, allowance);
471
+ dropped += records.length - batch.length;
472
+ attempted = batch.length;
473
+ if (!batch.length || !active()) return;
474
+ const identified = await options.identity();
475
+ const identity = typeof identified === "string" ? identified : identified.id;
476
+ if (typeof identified !== "string")
477
+ for (const record2 of batch) record2.identity_scope = identified.scope;
478
+ if (!active() || options.debug?.()) return;
479
+ if (!/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(
480
+ identity
481
+ )) {
482
+ dropped += batch.length;
483
+ return;
484
+ }
485
+ sent += batch.length;
486
+ await options.transport(batch, identity);
487
+ delivered += batch.length;
488
+ } catch {
489
+ dropped += attempted;
490
+ }
491
+ })().finally(() => {
492
+ flight = void 0;
493
+ try {
494
+ if (pending.size && active() && !timer)
495
+ timer = (options.schedule ?? schedule)(
496
+ () => void flush(),
497
+ options.flushIntervalMs ?? 6e4
498
+ );
499
+ } catch {
500
+ clear();
501
+ }
502
+ });
503
+ return flight;
504
+ };
505
+ const record = (event, operation, outcome, duration, input) => {
506
+ try {
507
+ if (!active()) {
508
+ clear();
509
+ return;
510
+ }
511
+ if (!configured || !catalog.operations.includes(operation) || !outcomes.includes(outcome))
512
+ return;
513
+ const properties = sanitizeProperties(input, catalog);
514
+ const key = JSON.stringify([event, operation, outcome, properties]);
515
+ let existing = pending.get(key);
516
+ if (!existing) {
517
+ if (pending.size >= (options.maxGroups ?? 64)) {
518
+ dropped++;
519
+ return;
520
+ }
521
+ existing = {
522
+ schema_version: 1,
523
+ event_id: crypto.randomUUID(),
524
+ timestamp: new Date(now()).toISOString(),
525
+ event,
526
+ product: options.context.product,
527
+ component: options.context.component,
528
+ version: options.context.version,
529
+ analytics_environment: options.context.environment ?? "production",
530
+ runtime_mode: options.context.runtimeMode ?? "unknown",
531
+ identity_scope: options.context.identityScope ?? "installation",
532
+ operation,
533
+ outcome,
534
+ properties,
535
+ count: 0,
536
+ duration_total_ms: 0,
537
+ duration_buckets: [0, 0, 0, 0, 0, 0]
538
+ };
539
+ pending.set(key, existing);
540
+ }
541
+ const elapsed = Math.max(
542
+ 0,
543
+ Math.min(864e5, Number.isFinite(duration) ? duration : 0)
544
+ );
545
+ existing.count = Math.min(Number.MAX_SAFE_INTEGER, existing.count + 1);
546
+ existing.duration_total_ms = Math.min(
547
+ Number.MAX_SAFE_INTEGER,
548
+ existing.duration_total_ms + elapsed
549
+ );
550
+ const index = durationBounds.findIndex((bound) => elapsed <= bound);
551
+ const bucket = index === -1 ? durationBounds.length : index;
552
+ existing.duration_buckets[bucket] = (existing.duration_buckets[bucket] ?? 0) + 1;
553
+ if (!timer)
554
+ timer = (options.schedule ?? schedule)(
555
+ () => void flush(),
556
+ options.flushIntervalMs ?? 6e4
557
+ );
558
+ } catch {
559
+ }
560
+ };
561
+ const start = (operation, properties = {}) => {
562
+ if (!active()) {
563
+ clear();
564
+ return noopOperation;
565
+ }
566
+ try {
567
+ const initial = sanitizeProperties(properties, catalog);
568
+ const began = now();
569
+ let ended = false;
570
+ return {
571
+ end(outcome = "success", extra = {}) {
572
+ if (ended) return;
573
+ ended = true;
574
+ try {
575
+ record("usage.operation", operation, outcome, now() - began, {
576
+ ...initial,
577
+ ...sanitizeProperties(extra, catalog)
578
+ });
579
+ } catch {
580
+ }
581
+ },
582
+ fail(error, extra = {}) {
583
+ if (ended) return;
584
+ try {
585
+ const failure = classifyUsageError(error, catalog);
586
+ this.end(failure.outcome, {
587
+ ...sanitizeProperties(extra, catalog),
588
+ ...failure.properties
589
+ });
590
+ } catch {
591
+ }
592
+ }
593
+ };
594
+ } catch {
595
+ return noopOperation;
596
+ }
597
+ };
598
+ return {
599
+ start,
600
+ feature(operation, properties = {}) {
601
+ record("usage.feature", operation, "success", 0, properties);
602
+ },
603
+ async measure(operation, callback, properties = {}, outcome) {
604
+ const operationScope = start(operation, properties);
605
+ try {
606
+ const result = await callback();
607
+ let status = "success";
608
+ try {
609
+ status = outcome?.(result) ?? status;
610
+ } catch {
611
+ }
612
+ operationScope.end(status);
613
+ return result;
614
+ } catch (error) {
615
+ operationScope.fail(error);
616
+ throw error;
617
+ }
618
+ },
619
+ flush,
620
+ dispose() {
621
+ disposed = true;
622
+ clear();
623
+ },
624
+ stats: () => ({ pending: pending.size, dropped, delivered })
625
+ };
626
+ }
627
+
628
+ // src/browser-node.ts
629
+ var clients = /* @__PURE__ */ new Map();
630
+ function createNodeUsageTelemetry(options) {
631
+ return createUsageTelemetry({
632
+ ...options,
633
+ identity: options.identity ?? (() => ""),
634
+ transport: options.transport ?? (async () => {
635
+ }),
636
+ enabled: () => false
637
+ });
638
+ }
639
+ function configureUsageTelemetry(component, client) {
640
+ if (clients.get(component) === client) return;
641
+ clients.get(component)?.dispose();
642
+ clients.set(component, client);
643
+ }
644
+ function getUsageTelemetry(component, version = "unknown", product = "sdk") {
645
+ let client = clients.get(component);
646
+ if (!client) {
647
+ client = createNodeUsageTelemetry({
648
+ context: { component, version, product }
649
+ });
650
+ clients.set(component, client);
651
+ }
652
+ return client;
653
+ }
654
+ function usageDisabled() {
655
+ return true;
656
+ }
657
+ function publicUsageConfiguration() {
658
+ return {
659
+ enabled: false,
660
+ debug: false,
661
+ environment: "production",
662
+ key: "",
663
+ host: "https://eu.i.posthog.com"
664
+ };
665
+ }
666
+ // Annotate the CommonJS export names for ESM import in node:
667
+ 0 && (module.exports = {
668
+ configureUsageTelemetry,
669
+ createNodeUsageTelemetry,
670
+ createUsageTelemetry,
671
+ getUsageTelemetry,
672
+ publicUsageConfiguration,
673
+ scale,
674
+ usageDisabled
675
+ });
676
+ //# sourceMappingURL=browser-node.js.map