@tangle-network/sdk-telemetry 0.60.78-develop.20261025200559.0984d38 → 0.60.78-develop.20261025204117.3cefa34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +22 -323
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -716
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,206 +1,6 @@
|
|
|
1
1
|
import { c as parseServerTiming } from "./server-timing-CTGu_pos.mjs";
|
|
2
2
|
import { ORCHESTRATOR_HOP_ID_HEADER, PROVISION_TRACE_ID_HEADER, PTID_PREFIX, SpanRecorder, isAdoptablePtid, mintPtid, monotonicNs, readOrMintPtid, spanDurationMs } from "./stage-span.mjs";
|
|
3
3
|
import { GEN_AI_CONVERSATION_ID, GEN_AI_CONVERSATION_ID as GEN_AI_CONVERSATION_ID$1, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OPERATION_NAME as GEN_AI_OPERATION_NAME$1, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_REQUEST_MODEL as GEN_AI_REQUEST_MODEL$1, GEN_AI_RESPONSE_MODEL, GEN_AI_RESPONSE_MODEL as GEN_AI_RESPONSE_MODEL$1, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS as GEN_AI_USAGE_INPUT_TOKENS$1, GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS as GEN_AI_USAGE_OUTPUT_TOKENS$1, SSEChunkParser, StreamUsageExtractor, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, addTokenUsage, consumeSSEStream, createStreamUsageExtractor, createUsageCallback, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, isFilePart, isReasoningPart, isTextPart, isToolPart, parseSSEData as parseSSEData$1, parseSSEStream, readTokenCostUsd, readTokenUsage, tokenCount, tokenUsageSource } from "@tangle-network/agent-core";
|
|
4
|
-
//#region src/credits.ts
|
|
5
|
-
const DEFAULT_CONFIG$2 = {
|
|
6
|
-
refreshIntervalMs: 6e4,
|
|
7
|
-
warningThreshold: .2,
|
|
8
|
-
criticalThreshold: .05
|
|
9
|
-
};
|
|
10
|
-
var CreditTracker = class {
|
|
11
|
-
config;
|
|
12
|
-
provider;
|
|
13
|
-
storage;
|
|
14
|
-
cachedBalance;
|
|
15
|
-
lastRefresh;
|
|
16
|
-
refreshTimer;
|
|
17
|
-
reservations = /* @__PURE__ */ new Map();
|
|
18
|
-
constructor(config, provider, storage) {
|
|
19
|
-
this.config = {
|
|
20
|
-
...DEFAULT_CONFIG$2,
|
|
21
|
-
...config
|
|
22
|
-
};
|
|
23
|
-
this.provider = provider;
|
|
24
|
-
this.storage = storage;
|
|
25
|
-
if (this.config.refreshIntervalMs > 0) this.startRefreshTimer();
|
|
26
|
-
}
|
|
27
|
-
async getBalance(forceRefresh = false) {
|
|
28
|
-
if (forceRefresh || !this.cachedBalance || this.isStale()) {
|
|
29
|
-
this.cachedBalance = await this.provider.getBalance();
|
|
30
|
-
this.lastRefresh = /* @__PURE__ */ new Date();
|
|
31
|
-
this.checkThresholds(this.cachedBalance);
|
|
32
|
-
if (this.storage) await this.storage.set(`credits:${this.config.projectRef}:balance`, this.cachedBalance);
|
|
33
|
-
this.config.onBalanceUpdate?.(this.cachedBalance);
|
|
34
|
-
}
|
|
35
|
-
return this.cachedBalance;
|
|
36
|
-
}
|
|
37
|
-
async getTransactions(options) {
|
|
38
|
-
return this.provider.getTransactions(options);
|
|
39
|
-
}
|
|
40
|
-
async hasCredits(amount) {
|
|
41
|
-
const balance = await this.getBalance();
|
|
42
|
-
const reservedTotal = this.getReservedTotal();
|
|
43
|
-
return balance.available - reservedTotal >= amount;
|
|
44
|
-
}
|
|
45
|
-
async reserve(amount, options) {
|
|
46
|
-
if (!await this.hasCredits(amount)) return null;
|
|
47
|
-
const reservationId = await this.provider.reserveCredit(amount);
|
|
48
|
-
if (!reservationId) return null;
|
|
49
|
-
const now = /* @__PURE__ */ new Date();
|
|
50
|
-
this.reservations.set(reservationId, {
|
|
51
|
-
amount,
|
|
52
|
-
createdAt: now,
|
|
53
|
-
expiresAt: options?.ttlMs ? new Date(now.getTime() + options.ttlMs) : void 0
|
|
54
|
-
});
|
|
55
|
-
return reservationId;
|
|
56
|
-
}
|
|
57
|
-
async release(reservationId) {
|
|
58
|
-
await this.provider.releaseReservation(reservationId);
|
|
59
|
-
this.reservations.delete(reservationId);
|
|
60
|
-
}
|
|
61
|
-
async charge(reservationId, actualAmount) {
|
|
62
|
-
const transaction = await this.provider.chargeReservation(reservationId, actualAmount);
|
|
63
|
-
this.reservations.delete(reservationId);
|
|
64
|
-
await this.getBalance(true);
|
|
65
|
-
return transaction;
|
|
66
|
-
}
|
|
67
|
-
async chargeImmediate(amount, _description) {
|
|
68
|
-
const reservationId = await this.reserve(amount);
|
|
69
|
-
if (!reservationId) return null;
|
|
70
|
-
return this.charge(reservationId, amount);
|
|
71
|
-
}
|
|
72
|
-
getReservedTotal() {
|
|
73
|
-
this.cleanupExpiredReservations();
|
|
74
|
-
let total = 0;
|
|
75
|
-
for (const reservation of this.reservations.values()) total += reservation.amount;
|
|
76
|
-
return total;
|
|
77
|
-
}
|
|
78
|
-
getEffectiveBalance() {
|
|
79
|
-
const balance = this.cachedBalance;
|
|
80
|
-
if (!balance) return 0;
|
|
81
|
-
return balance.available - this.getReservedTotal();
|
|
82
|
-
}
|
|
83
|
-
getUsagePercent() {
|
|
84
|
-
const balance = this.cachedBalance;
|
|
85
|
-
if (!balance || balance.limit === 0) return 0;
|
|
86
|
-
return balance.used / balance.limit * 100;
|
|
87
|
-
}
|
|
88
|
-
getRemainingPercent() {
|
|
89
|
-
const balance = this.cachedBalance;
|
|
90
|
-
if (!balance || balance.limit === 0) return 100;
|
|
91
|
-
return balance.available / balance.limit * 100;
|
|
92
|
-
}
|
|
93
|
-
isLow() {
|
|
94
|
-
return this.getRemainingPercent() / 100 <= this.config.warningThreshold;
|
|
95
|
-
}
|
|
96
|
-
isCritical() {
|
|
97
|
-
return this.getRemainingPercent() / 100 <= this.config.criticalThreshold;
|
|
98
|
-
}
|
|
99
|
-
async close() {
|
|
100
|
-
this.stopRefreshTimer();
|
|
101
|
-
for (const [id] of this.reservations) try {
|
|
102
|
-
await this.release(id);
|
|
103
|
-
} catch {}
|
|
104
|
-
}
|
|
105
|
-
isStale() {
|
|
106
|
-
if (!this.lastRefresh) return true;
|
|
107
|
-
return Date.now() - this.lastRefresh.getTime() > this.config.refreshIntervalMs;
|
|
108
|
-
}
|
|
109
|
-
checkThresholds(balance) {
|
|
110
|
-
if (!balance.limit || balance.limit <= 0) return;
|
|
111
|
-
const remainingPercent = balance.available / balance.limit;
|
|
112
|
-
if (remainingPercent <= this.config.criticalThreshold) this.config.onCriticalBalance?.(balance);
|
|
113
|
-
else if (remainingPercent <= this.config.warningThreshold) this.config.onLowBalance?.(balance);
|
|
114
|
-
}
|
|
115
|
-
cleanupExpiredReservations() {
|
|
116
|
-
const now = Date.now();
|
|
117
|
-
for (const [id, reservation] of this.reservations) if (reservation.expiresAt && reservation.expiresAt.getTime() < now) this.reservations.delete(id);
|
|
118
|
-
}
|
|
119
|
-
startRefreshTimer() {
|
|
120
|
-
if (this.refreshTimer) return;
|
|
121
|
-
this.refreshTimer = setInterval(() => this.getBalance(true), this.config.refreshIntervalMs);
|
|
122
|
-
}
|
|
123
|
-
stopRefreshTimer() {
|
|
124
|
-
if (this.refreshTimer) {
|
|
125
|
-
clearInterval(this.refreshTimer);
|
|
126
|
-
this.refreshTimer = void 0;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
var MemoryCreditProvider = class {
|
|
131
|
-
balance;
|
|
132
|
-
transactions = [];
|
|
133
|
-
reservations = /* @__PURE__ */ new Map();
|
|
134
|
-
constructor(initialBalance = {}) {
|
|
135
|
-
this.balance = {
|
|
136
|
-
available: initialBalance.available ?? 1e3,
|
|
137
|
-
used: initialBalance.used ?? 0,
|
|
138
|
-
limit: initialBalance.limit ?? 1e3,
|
|
139
|
-
currency: initialBalance.currency ?? "credits"
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
async getBalance() {
|
|
143
|
-
return { ...this.balance };
|
|
144
|
-
}
|
|
145
|
-
async getTransactions(options) {
|
|
146
|
-
let result = [...this.transactions];
|
|
147
|
-
if (options?.since) {
|
|
148
|
-
const since = options.since;
|
|
149
|
-
result = result.filter((t) => t.timestamp >= since);
|
|
150
|
-
}
|
|
151
|
-
result = result.slice(options?.offset ?? 0, (options?.offset ?? 0) + (options?.limit ?? 100));
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
|
-
async checkCredit(amount) {
|
|
155
|
-
const reservedTotal = Array.from(this.reservations.values()).reduce((sum, amt) => sum + amt, 0);
|
|
156
|
-
return this.balance.available - reservedTotal >= amount;
|
|
157
|
-
}
|
|
158
|
-
async reserveCredit(amount) {
|
|
159
|
-
if (!await this.checkCredit(amount)) return null;
|
|
160
|
-
const id = `res-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
161
|
-
this.reservations.set(id, amount);
|
|
162
|
-
return id;
|
|
163
|
-
}
|
|
164
|
-
async releaseReservation(reservationId) {
|
|
165
|
-
this.reservations.delete(reservationId);
|
|
166
|
-
}
|
|
167
|
-
async chargeReservation(reservationId, actualAmount) {
|
|
168
|
-
const reserved = this.reservations.get(reservationId);
|
|
169
|
-
if (reserved === void 0) throw new Error(`Reservation not found: ${reservationId}`);
|
|
170
|
-
const chargeAmount = actualAmount ?? reserved;
|
|
171
|
-
this.reservations.delete(reservationId);
|
|
172
|
-
this.balance.available -= chargeAmount;
|
|
173
|
-
this.balance.used += chargeAmount;
|
|
174
|
-
const transaction = {
|
|
175
|
-
id: `txn-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
176
|
-
type: "charge",
|
|
177
|
-
amount: chargeAmount,
|
|
178
|
-
balance: this.balance.available,
|
|
179
|
-
description: `Charged from reservation ${reservationId}`,
|
|
180
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
181
|
-
};
|
|
182
|
-
this.transactions.unshift(transaction);
|
|
183
|
-
return transaction;
|
|
184
|
-
}
|
|
185
|
-
addCredits(amount, description) {
|
|
186
|
-
this.balance.available += amount;
|
|
187
|
-
this.balance.limit += amount;
|
|
188
|
-
const transaction = {
|
|
189
|
-
id: `txn-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
190
|
-
type: "grant",
|
|
191
|
-
amount,
|
|
192
|
-
balance: this.balance.available,
|
|
193
|
-
description,
|
|
194
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
195
|
-
};
|
|
196
|
-
this.transactions.unshift(transaction);
|
|
197
|
-
return transaction;
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
function createCreditTracker(config, provider, storage) {
|
|
201
|
-
return new CreditTracker(config, provider, storage);
|
|
202
|
-
}
|
|
203
|
-
//#endregion
|
|
204
4
|
//#region src/enrichment/parse.ts
|
|
205
5
|
const VALID_PRODUCTS = [
|
|
206
6
|
"vibe_coding",
|
|
@@ -1595,521 +1395,6 @@ function createTraceCollector(config) {
|
|
|
1595
1395
|
return new TraceCollector(config);
|
|
1596
1396
|
}
|
|
1597
1397
|
//#endregion
|
|
1598
|
-
|
|
1599
|
-
const DEFAULT_CONFIG$1 = {
|
|
1600
|
-
enabled: true,
|
|
1601
|
-
flushIntervalMs: 3e4,
|
|
1602
|
-
maxBatchSize: 100,
|
|
1603
|
-
maxQueueSize: 1e3,
|
|
1604
|
-
sampleRate: 1,
|
|
1605
|
-
excludePatterns: [],
|
|
1606
|
-
includeMetadata: true,
|
|
1607
|
-
persistOffline: true
|
|
1608
|
-
};
|
|
1609
|
-
var TelemetryTracker = class {
|
|
1610
|
-
config;
|
|
1611
|
-
sinks = [];
|
|
1612
|
-
queue = [];
|
|
1613
|
-
storage;
|
|
1614
|
-
sequence = 0;
|
|
1615
|
-
flushTimer;
|
|
1616
|
-
sessionStartTime;
|
|
1617
|
-
isFlushing = false;
|
|
1618
|
-
constructor(config, storage) {
|
|
1619
|
-
this.config = {
|
|
1620
|
-
...DEFAULT_CONFIG$1,
|
|
1621
|
-
...config
|
|
1622
|
-
};
|
|
1623
|
-
this.storage = storage;
|
|
1624
|
-
if (this.config.enabled && this.config.flushIntervalMs > 0) this.startFlushTimer();
|
|
1625
|
-
}
|
|
1626
|
-
addSink(sink) {
|
|
1627
|
-
this.sinks.push(sink);
|
|
1628
|
-
return this;
|
|
1629
|
-
}
|
|
1630
|
-
removeSink(name) {
|
|
1631
|
-
const index = this.sinks.findIndex((s) => s.name === name);
|
|
1632
|
-
if (index !== -1) this.sinks.splice(index, 1);
|
|
1633
|
-
return this;
|
|
1634
|
-
}
|
|
1635
|
-
startSession(metadata) {
|
|
1636
|
-
const sessionId = this.config.sessionId ?? `session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
1637
|
-
this.sessionStartTime = /* @__PURE__ */ new Date();
|
|
1638
|
-
this.track("session_start", "session.started", {
|
|
1639
|
-
...metadata,
|
|
1640
|
-
sessionId,
|
|
1641
|
-
startTime: this.sessionStartTime.toISOString()
|
|
1642
|
-
});
|
|
1643
|
-
return sessionId;
|
|
1644
|
-
}
|
|
1645
|
-
endSession(metadata) {
|
|
1646
|
-
const duration = this.sessionStartTime ? Date.now() - this.sessionStartTime.getTime() : 0;
|
|
1647
|
-
this.track("session_end", "session.ended", {
|
|
1648
|
-
...metadata,
|
|
1649
|
-
durationMs: duration,
|
|
1650
|
-
eventCount: this.sequence
|
|
1651
|
-
});
|
|
1652
|
-
this.flush();
|
|
1653
|
-
}
|
|
1654
|
-
track(type, name, data = {}) {
|
|
1655
|
-
if (!this.config.enabled) return;
|
|
1656
|
-
if (!this.shouldSample()) return;
|
|
1657
|
-
if (this.isExcluded(name)) return;
|
|
1658
|
-
const event = {
|
|
1659
|
-
id: `evt-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
1660
|
-
type,
|
|
1661
|
-
name,
|
|
1662
|
-
projectRef: this.config.projectRef,
|
|
1663
|
-
sessionId: this.config.sessionId,
|
|
1664
|
-
userId: this.config.userId,
|
|
1665
|
-
data: this.config.includeMetadata ? this.enrichData(data) : data,
|
|
1666
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1667
|
-
sequence: ++this.sequence
|
|
1668
|
-
};
|
|
1669
|
-
this.enqueue(event);
|
|
1670
|
-
}
|
|
1671
|
-
trackPerformance(metric) {
|
|
1672
|
-
this.track("performance", `perf.${metric.name}`, {
|
|
1673
|
-
value: metric.value,
|
|
1674
|
-
unit: metric.unit,
|
|
1675
|
-
tags: metric.tags
|
|
1676
|
-
});
|
|
1677
|
-
}
|
|
1678
|
-
trackError(error, context) {
|
|
1679
|
-
const errorData = error instanceof Error ? {
|
|
1680
|
-
message: error.message,
|
|
1681
|
-
name: error.name,
|
|
1682
|
-
stack: error.stack
|
|
1683
|
-
} : { message: error };
|
|
1684
|
-
this.track("error", "error.occurred", {
|
|
1685
|
-
...errorData,
|
|
1686
|
-
...context
|
|
1687
|
-
});
|
|
1688
|
-
}
|
|
1689
|
-
trackApiRequest(method, path, status, durationMs, metadata) {
|
|
1690
|
-
this.track("api_request", `api.${method.toLowerCase()}.${path}`, {
|
|
1691
|
-
method,
|
|
1692
|
-
path,
|
|
1693
|
-
status,
|
|
1694
|
-
durationMs,
|
|
1695
|
-
...metadata
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
|
-
trackAgentExecution(identifier, executionId, durationMs, success, metadata) {
|
|
1699
|
-
this.track("agent_execution", `agent.${identifier}`, {
|
|
1700
|
-
identifier,
|
|
1701
|
-
executionId,
|
|
1702
|
-
durationMs,
|
|
1703
|
-
success,
|
|
1704
|
-
...metadata
|
|
1705
|
-
});
|
|
1706
|
-
}
|
|
1707
|
-
async flush() {
|
|
1708
|
-
if (this.isFlushing || this.queue.length === 0) return;
|
|
1709
|
-
this.isFlushing = true;
|
|
1710
|
-
try {
|
|
1711
|
-
const events = this.queue.splice(0, this.config.maxBatchSize);
|
|
1712
|
-
await Promise.all(this.sinks.map((sink) => sink.send(events)));
|
|
1713
|
-
if (this.config.persistOffline && this.storage) await this.clearPersistedEvents(events.map((e) => e.id));
|
|
1714
|
-
} catch (_error) {
|
|
1715
|
-
if (this.config.persistOffline && this.storage) await this.persistEvents(this.queue);
|
|
1716
|
-
} finally {
|
|
1717
|
-
this.isFlushing = false;
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
async close() {
|
|
1721
|
-
this.stopFlushTimer();
|
|
1722
|
-
await this.flush();
|
|
1723
|
-
await Promise.all(this.sinks.map((sink) => sink.close()));
|
|
1724
|
-
}
|
|
1725
|
-
getQueueSize() {
|
|
1726
|
-
return this.queue.length;
|
|
1727
|
-
}
|
|
1728
|
-
isEnabled() {
|
|
1729
|
-
return this.config.enabled;
|
|
1730
|
-
}
|
|
1731
|
-
enable() {
|
|
1732
|
-
this.config.enabled = true;
|
|
1733
|
-
this.startFlushTimer();
|
|
1734
|
-
}
|
|
1735
|
-
disable() {
|
|
1736
|
-
this.config.enabled = false;
|
|
1737
|
-
this.stopFlushTimer();
|
|
1738
|
-
}
|
|
1739
|
-
enqueue(event) {
|
|
1740
|
-
if (this.queue.length >= this.config.maxQueueSize) this.queue.shift();
|
|
1741
|
-
this.queue.push(event);
|
|
1742
|
-
if (this.queue.length >= this.config.maxBatchSize) this.flush();
|
|
1743
|
-
if (this.config.persistOffline && this.storage) this.persistEvent(event);
|
|
1744
|
-
}
|
|
1745
|
-
shouldSample() {
|
|
1746
|
-
return Math.random() < this.config.sampleRate;
|
|
1747
|
-
}
|
|
1748
|
-
isExcluded(name) {
|
|
1749
|
-
return this.config.excludePatterns.some((pattern) => {
|
|
1750
|
-
if (pattern.includes("*")) return new RegExp(`^${pattern.replace(/\*/g, ".*").replace(/\?/g, ".")}$`).test(name);
|
|
1751
|
-
return name === pattern;
|
|
1752
|
-
});
|
|
1753
|
-
}
|
|
1754
|
-
enrichData(data) {
|
|
1755
|
-
return {
|
|
1756
|
-
...data,
|
|
1757
|
-
_meta: {
|
|
1758
|
-
timestamp: Date.now(),
|
|
1759
|
-
platform: typeof navigator !== "undefined" ? navigator.userAgent : "node",
|
|
1760
|
-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
startFlushTimer() {
|
|
1765
|
-
if (this.flushTimer) return;
|
|
1766
|
-
this.flushTimer = setInterval(() => this.flush(), this.config.flushIntervalMs);
|
|
1767
|
-
}
|
|
1768
|
-
stopFlushTimer() {
|
|
1769
|
-
if (this.flushTimer) {
|
|
1770
|
-
clearInterval(this.flushTimer);
|
|
1771
|
-
this.flushTimer = void 0;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
async persistEvent(event) {
|
|
1775
|
-
if (!this.storage) return;
|
|
1776
|
-
const key = `telemetry:${event.id}`;
|
|
1777
|
-
await this.storage.set(key, event);
|
|
1778
|
-
}
|
|
1779
|
-
async persistEvents(events) {
|
|
1780
|
-
if (!this.storage) return;
|
|
1781
|
-
await Promise.all(events.map((e) => this.persistEvent(e)));
|
|
1782
|
-
}
|
|
1783
|
-
async clearPersistedEvents(ids) {
|
|
1784
|
-
if (!this.storage) return;
|
|
1785
|
-
await Promise.all(ids.map((id) => this.storage?.delete(`telemetry:${id}`)));
|
|
1786
|
-
}
|
|
1787
|
-
async loadPersistedEvents() {
|
|
1788
|
-
if (!this.storage) return [];
|
|
1789
|
-
const telemetryKeys = (await this.storage.keys()).filter((k) => k.startsWith("telemetry:"));
|
|
1790
|
-
const events = [];
|
|
1791
|
-
for (const key of telemetryKeys) {
|
|
1792
|
-
const event = await this.storage.get(key);
|
|
1793
|
-
if (event) events.push(event);
|
|
1794
|
-
}
|
|
1795
|
-
return events.sort((a, b) => a.sequence - b.sequence);
|
|
1796
|
-
}
|
|
1797
|
-
};
|
|
1798
|
-
function createTelemetryTracker(config, storage) {
|
|
1799
|
-
return new TelemetryTracker(config, storage);
|
|
1800
|
-
}
|
|
1801
|
-
//#endregion
|
|
1802
|
-
//#region src/usage.ts
|
|
1803
|
-
const DEFAULT_CONFIG = {
|
|
1804
|
-
autoTrack: true,
|
|
1805
|
-
trackApiCalls: true,
|
|
1806
|
-
trackAgentExecutions: true,
|
|
1807
|
-
trackErrors: true,
|
|
1808
|
-
batchSize: 50,
|
|
1809
|
-
flushIntervalMs: 3e4
|
|
1810
|
-
};
|
|
1811
|
-
const OPERATION_COSTS = {
|
|
1812
|
-
"api.get": .001,
|
|
1813
|
-
"api.post": .002,
|
|
1814
|
-
"api.put": .002,
|
|
1815
|
-
"api.delete": .001,
|
|
1816
|
-
"agent.execution": .01,
|
|
1817
|
-
"agent.streaming": .015,
|
|
1818
|
-
"token.input": 1e-5,
|
|
1819
|
-
"token.output": 3e-5,
|
|
1820
|
-
default: .001
|
|
1821
|
-
};
|
|
1822
|
-
var UsageTracker = class {
|
|
1823
|
-
config;
|
|
1824
|
-
provider;
|
|
1825
|
-
storage;
|
|
1826
|
-
queue = [];
|
|
1827
|
-
flushTimer;
|
|
1828
|
-
isFlushing = false;
|
|
1829
|
-
sessionMetrics = {
|
|
1830
|
-
totalCredits: 0,
|
|
1831
|
-
totalOperations: 0,
|
|
1832
|
-
totalDurationMs: 0,
|
|
1833
|
-
totalInputTokens: 0,
|
|
1834
|
-
totalOutputTokens: 0,
|
|
1835
|
-
operationCounts: /* @__PURE__ */ new Map(),
|
|
1836
|
-
startTime: Date.now()
|
|
1837
|
-
};
|
|
1838
|
-
constructor(config, provider, storage) {
|
|
1839
|
-
this.config = {
|
|
1840
|
-
...DEFAULT_CONFIG,
|
|
1841
|
-
...config
|
|
1842
|
-
};
|
|
1843
|
-
this.provider = provider;
|
|
1844
|
-
this.storage = storage;
|
|
1845
|
-
if (this.config.flushIntervalMs > 0) this.startFlushTimer();
|
|
1846
|
-
}
|
|
1847
|
-
recordApiCall(metric) {
|
|
1848
|
-
if (!this.config.trackApiCalls) return;
|
|
1849
|
-
const operation = `api.${metric.method.toLowerCase()}`;
|
|
1850
|
-
const credits = this.calculateCost(operation, {
|
|
1851
|
-
durationMs: metric.durationMs,
|
|
1852
|
-
requestSize: metric.requestSize,
|
|
1853
|
-
responseSize: metric.responseSize
|
|
1854
|
-
});
|
|
1855
|
-
this.record({
|
|
1856
|
-
projectRef: this.config.projectRef,
|
|
1857
|
-
userId: this.config.userId,
|
|
1858
|
-
operation,
|
|
1859
|
-
credits,
|
|
1860
|
-
durationMs: metric.durationMs,
|
|
1861
|
-
metadata: {
|
|
1862
|
-
path: metric.path,
|
|
1863
|
-
status: metric.status,
|
|
1864
|
-
requestSize: metric.requestSize,
|
|
1865
|
-
responseSize: metric.responseSize,
|
|
1866
|
-
error: metric.error
|
|
1867
|
-
}
|
|
1868
|
-
});
|
|
1869
|
-
}
|
|
1870
|
-
recordAgentExecution(metric) {
|
|
1871
|
-
if (!this.config.trackAgentExecutions) return;
|
|
1872
|
-
const operation = "agent.execution";
|
|
1873
|
-
const tokenCost = (metric.inputTokens ?? 0) * OPERATION_COSTS["token.input"] + (metric.outputTokens ?? 0) * OPERATION_COSTS["token.output"];
|
|
1874
|
-
const credits = this.calculateCost(operation, { durationMs: metric.durationMs }) + tokenCost;
|
|
1875
|
-
this.record({
|
|
1876
|
-
projectRef: metric.projectRef,
|
|
1877
|
-
userId: this.config.userId,
|
|
1878
|
-
operation,
|
|
1879
|
-
credits,
|
|
1880
|
-
durationMs: metric.durationMs,
|
|
1881
|
-
inputTokens: metric.inputTokens,
|
|
1882
|
-
outputTokens: metric.outputTokens,
|
|
1883
|
-
metadata: {
|
|
1884
|
-
identifier: metric.identifier,
|
|
1885
|
-
executionId: metric.executionId,
|
|
1886
|
-
toolCalls: metric.toolCalls,
|
|
1887
|
-
success: metric.success,
|
|
1888
|
-
error: metric.error
|
|
1889
|
-
}
|
|
1890
|
-
});
|
|
1891
|
-
}
|
|
1892
|
-
recordError(error, operation) {
|
|
1893
|
-
if (!this.config.trackErrors) return;
|
|
1894
|
-
this.record({
|
|
1895
|
-
projectRef: this.config.projectRef,
|
|
1896
|
-
userId: this.config.userId,
|
|
1897
|
-
operation: `error.${operation}`,
|
|
1898
|
-
credits: 0,
|
|
1899
|
-
metadata: {
|
|
1900
|
-
error: error instanceof Error ? error.message : error,
|
|
1901
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
1902
|
-
}
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
record(usage) {
|
|
1906
|
-
this.queue.push(usage);
|
|
1907
|
-
this.sessionMetrics.totalCredits += usage.credits;
|
|
1908
|
-
this.sessionMetrics.totalOperations++;
|
|
1909
|
-
this.sessionMetrics.totalDurationMs += usage.durationMs ?? 0;
|
|
1910
|
-
this.sessionMetrics.totalInputTokens += usage.inputTokens ?? 0;
|
|
1911
|
-
this.sessionMetrics.totalOutputTokens += usage.outputTokens ?? 0;
|
|
1912
|
-
const count = this.sessionMetrics.operationCounts.get(usage.operation) ?? 0;
|
|
1913
|
-
this.sessionMetrics.operationCounts.set(usage.operation, count + 1);
|
|
1914
|
-
if (this.queue.length >= this.config.batchSize) this.flush();
|
|
1915
|
-
}
|
|
1916
|
-
async flush() {
|
|
1917
|
-
if (this.isFlushing || this.queue.length === 0) return;
|
|
1918
|
-
this.isFlushing = true;
|
|
1919
|
-
const records = this.queue.splice(0, this.config.batchSize);
|
|
1920
|
-
const providerFailed = /* @__PURE__ */ new Set();
|
|
1921
|
-
const providerDone = /* @__PURE__ */ new Set();
|
|
1922
|
-
try {
|
|
1923
|
-
if (this.provider) {
|
|
1924
|
-
const results = await Promise.allSettled(records.map((r) => this.provider?.recordUsage(r)));
|
|
1925
|
-
for (let i = 0; i < records.length; i++) if (results[i].status === "rejected") providerFailed.add(records[i]);
|
|
1926
|
-
else providerDone.add(records[i]);
|
|
1927
|
-
if (providerFailed.size > 0) this.queue.unshift(...providerFailed);
|
|
1928
|
-
}
|
|
1929
|
-
if (this.storage) {
|
|
1930
|
-
const toPersist = providerFailed.size > 0 ? records.filter((r) => !providerFailed.has(r)) : records;
|
|
1931
|
-
if (toPersist.length > 0) await this.persistRecords(toPersist);
|
|
1932
|
-
}
|
|
1933
|
-
} catch (error) {
|
|
1934
|
-
const firstFailed = typeof error?.firstFailedIndex === "number" ? error.firstFailedIndex : 0;
|
|
1935
|
-
const unwritten = records.slice(firstFailed);
|
|
1936
|
-
if (providerDone.size > 0) console.warn(`[usage-tracker] storage persistence failed for ${providerDone.size} provider-accepted records — local audit trail incomplete`, error instanceof Error ? error.message : String(error));
|
|
1937
|
-
const unhandled = unwritten.filter((r) => !providerFailed.has(r) && !providerDone.has(r));
|
|
1938
|
-
if (unhandled.length > 0) this.queue.unshift(...unhandled);
|
|
1939
|
-
} finally {
|
|
1940
|
-
this.isFlushing = false;
|
|
1941
|
-
}
|
|
1942
|
-
}
|
|
1943
|
-
async getUsage(options) {
|
|
1944
|
-
if (this.provider) return this.provider.getUsage({
|
|
1945
|
-
projectRef: this.config.projectRef,
|
|
1946
|
-
...options
|
|
1947
|
-
});
|
|
1948
|
-
return this.loadPersistedRecords(options);
|
|
1949
|
-
}
|
|
1950
|
-
async getSummary(period = "day") {
|
|
1951
|
-
if (this.provider) return this.provider.getSummary(this.config.projectRef, period);
|
|
1952
|
-
return this.generateLocalSummary(period);
|
|
1953
|
-
}
|
|
1954
|
-
getSessionMetrics() {
|
|
1955
|
-
return {
|
|
1956
|
-
totalCredits: this.sessionMetrics.totalCredits,
|
|
1957
|
-
totalOperations: this.sessionMetrics.totalOperations,
|
|
1958
|
-
totalDurationMs: this.sessionMetrics.totalDurationMs,
|
|
1959
|
-
totalInputTokens: this.sessionMetrics.totalInputTokens,
|
|
1960
|
-
totalOutputTokens: this.sessionMetrics.totalOutputTokens,
|
|
1961
|
-
operationBreakdown: Object.fromEntries(this.sessionMetrics.operationCounts),
|
|
1962
|
-
sessionDurationMs: Date.now() - this.sessionMetrics.startTime
|
|
1963
|
-
};
|
|
1964
|
-
}
|
|
1965
|
-
resetSessionMetrics() {
|
|
1966
|
-
this.sessionMetrics = {
|
|
1967
|
-
totalCredits: 0,
|
|
1968
|
-
totalOperations: 0,
|
|
1969
|
-
totalDurationMs: 0,
|
|
1970
|
-
totalInputTokens: 0,
|
|
1971
|
-
totalOutputTokens: 0,
|
|
1972
|
-
operationCounts: /* @__PURE__ */ new Map(),
|
|
1973
|
-
startTime: Date.now()
|
|
1974
|
-
};
|
|
1975
|
-
}
|
|
1976
|
-
async close() {
|
|
1977
|
-
this.stopFlushTimer();
|
|
1978
|
-
await this.flush();
|
|
1979
|
-
}
|
|
1980
|
-
calculateCost(operation, factors) {
|
|
1981
|
-
let cost = OPERATION_COSTS[operation] ?? OPERATION_COSTS.default;
|
|
1982
|
-
if (factors.durationMs) cost += factors.durationMs / 1e3 * .001;
|
|
1983
|
-
if (factors.requestSize) cost += factors.requestSize / 1024 * 1e-4;
|
|
1984
|
-
if (factors.responseSize) cost += factors.responseSize / 1024 * 1e-4;
|
|
1985
|
-
return Math.round(cost * 1e5) / 1e5;
|
|
1986
|
-
}
|
|
1987
|
-
async persistRecords(records) {
|
|
1988
|
-
if (!this.storage) return;
|
|
1989
|
-
const timestamp = Date.now();
|
|
1990
|
-
for (let i = 0; i < records.length; i++) {
|
|
1991
|
-
const record = records[i];
|
|
1992
|
-
const id = `usage-${timestamp}-${i}`;
|
|
1993
|
-
try {
|
|
1994
|
-
await this.storage.set(`usage:${id}`, {
|
|
1995
|
-
...record,
|
|
1996
|
-
id,
|
|
1997
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
1998
|
-
});
|
|
1999
|
-
} catch (err) {
|
|
2000
|
-
throw Object.assign(err instanceof Error ? err : new Error(String(err)), { firstFailedIndex: i });
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
async loadPersistedRecords(options) {
|
|
2005
|
-
if (!this.storage) return [];
|
|
2006
|
-
const usageKeys = (await this.storage.keys()).filter((k) => k.startsWith("usage:"));
|
|
2007
|
-
const records = [];
|
|
2008
|
-
for (const key of usageKeys) {
|
|
2009
|
-
const record = await this.storage.get(key);
|
|
2010
|
-
if (!record) continue;
|
|
2011
|
-
if (options?.since && record.timestamp < options.since) continue;
|
|
2012
|
-
if (options?.until && record.timestamp > options.until) continue;
|
|
2013
|
-
records.push(record);
|
|
2014
|
-
}
|
|
2015
|
-
records.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
2016
|
-
return options?.limit ? records.slice(0, options.limit) : records;
|
|
2017
|
-
}
|
|
2018
|
-
async generateLocalSummary(period) {
|
|
2019
|
-
const now = /* @__PURE__ */ new Date();
|
|
2020
|
-
const periodStart = this.getPeriodStart(now, period);
|
|
2021
|
-
const records = await this.loadPersistedRecords({
|
|
2022
|
-
since: periodStart,
|
|
2023
|
-
until: now
|
|
2024
|
-
});
|
|
2025
|
-
const operationBreakdown = {};
|
|
2026
|
-
let totalCredits = 0;
|
|
2027
|
-
let totalDurationMs = 0;
|
|
2028
|
-
let totalInputTokens = 0;
|
|
2029
|
-
let totalOutputTokens = 0;
|
|
2030
|
-
for (const record of records) {
|
|
2031
|
-
totalCredits += record.credits;
|
|
2032
|
-
totalDurationMs += record.durationMs ?? 0;
|
|
2033
|
-
totalInputTokens += record.inputTokens ?? 0;
|
|
2034
|
-
totalOutputTokens += record.outputTokens ?? 0;
|
|
2035
|
-
operationBreakdown[record.operation] = (operationBreakdown[record.operation] ?? 0) + 1;
|
|
2036
|
-
}
|
|
2037
|
-
return {
|
|
2038
|
-
projectRef: this.config.projectRef,
|
|
2039
|
-
period,
|
|
2040
|
-
periodStart,
|
|
2041
|
-
periodEnd: now,
|
|
2042
|
-
totalCredits,
|
|
2043
|
-
totalOperations: records.length,
|
|
2044
|
-
totalDurationMs,
|
|
2045
|
-
totalInputTokens,
|
|
2046
|
-
totalOutputTokens,
|
|
2047
|
-
operationBreakdown
|
|
2048
|
-
};
|
|
2049
|
-
}
|
|
2050
|
-
getPeriodStart(now, period) {
|
|
2051
|
-
const start = new Date(now);
|
|
2052
|
-
switch (period) {
|
|
2053
|
-
case "hour":
|
|
2054
|
-
start.setMinutes(0, 0, 0);
|
|
2055
|
-
break;
|
|
2056
|
-
case "day":
|
|
2057
|
-
start.setHours(0, 0, 0, 0);
|
|
2058
|
-
break;
|
|
2059
|
-
case "week":
|
|
2060
|
-
start.setDate(start.getDate() - start.getDay());
|
|
2061
|
-
start.setHours(0, 0, 0, 0);
|
|
2062
|
-
break;
|
|
2063
|
-
case "month":
|
|
2064
|
-
start.setDate(1);
|
|
2065
|
-
start.setHours(0, 0, 0, 0);
|
|
2066
|
-
break;
|
|
2067
|
-
}
|
|
2068
|
-
return start;
|
|
2069
|
-
}
|
|
2070
|
-
startFlushTimer() {
|
|
2071
|
-
if (this.flushTimer) return;
|
|
2072
|
-
this.flushTimer = setInterval(() => this.flush(), this.config.flushIntervalMs);
|
|
2073
|
-
}
|
|
2074
|
-
stopFlushTimer() {
|
|
2075
|
-
if (this.flushTimer) {
|
|
2076
|
-
clearInterval(this.flushTimer);
|
|
2077
|
-
this.flushTimer = void 0;
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
};
|
|
2081
|
-
function createUsageInterceptor(tracker) {
|
|
2082
|
-
return {
|
|
2083
|
-
onRequest(ctx) {
|
|
2084
|
-
return ctx;
|
|
2085
|
-
},
|
|
2086
|
-
onResponse(ctx) {
|
|
2087
|
-
const durationMs = Date.now() - ctx.startedAt;
|
|
2088
|
-
tracker.recordApiCall({
|
|
2089
|
-
path: new URL(ctx.request.url).pathname,
|
|
2090
|
-
method: ctx.request.method,
|
|
2091
|
-
status: ctx.response.status,
|
|
2092
|
-
durationMs,
|
|
2093
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2094
|
-
});
|
|
2095
|
-
},
|
|
2096
|
-
onError(ctx) {
|
|
2097
|
-
const durationMs = Date.now() - ctx.startedAt;
|
|
2098
|
-
tracker.recordApiCall({
|
|
2099
|
-
path: new URL(ctx.request.url).pathname,
|
|
2100
|
-
method: ctx.request.method,
|
|
2101
|
-
status: 0,
|
|
2102
|
-
durationMs,
|
|
2103
|
-
error: ctx.error.message,
|
|
2104
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2105
|
-
});
|
|
2106
|
-
}
|
|
2107
|
-
};
|
|
2108
|
-
}
|
|
2109
|
-
function createUsageTracker(config, provider, storage) {
|
|
2110
|
-
return new UsageTracker(config, provider, storage);
|
|
2111
|
-
}
|
|
2112
|
-
//#endregion
|
|
2113
|
-
export { ConsoleTelemetrySink, CreditTracker, GEN_AI_CONVERSATION_ID, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, HttpTelemetrySink, LangfuseSink, MemoryCreditProvider, MultiTelemetrySink, ORCHESTRATOR_HOP_ID_HEADER, OtelTelemetrySink, PROVISION_TRACE_ID_HEADER, PTID_PREFIX, SSEChunkParser, SpanRecorder, StreamUsageExtractor, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, TelemetryTracker, TestTelemetrySink, TraceCollector, UsageTracker, addTokenUsage, consumeSSEStream, createConsoleSink, createCreditTracker, createEmptyContext, createHttpSink, createLangfuseSinkFromEnv, createOtelSink, createOtelSinkFromEnv, createStreamUsageExtractor, createTelemetryTracker, createTestSink, createTraceCollector, createUsageCallback, createUsageInterceptor, createUsageTracker, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, initOtelProvider, isAdoptablePtid, isBuildResultEvent, isCompletionEvent, isCustomEvent, isDiagnosticEvent, isEnvironmentEvent, isErrorEvent, isFileChangeEvent, isFilePart, isMessagePartUpdatedEvent, isMessageUpdatedEvent, isReasoningPart, isTestResultEvent, isTextPart, isToolPart, mintPtid, monotonicNs, parseMetadataBlob, parseSSEData, parseSSEStream, parseServerTiming, readOrMintPtid, readTokenCostUsd, readTokenUsage, shutdownOtelProvider, spanDurationMs, sseToSignal, sseToTraceEvent, tokenCount, tokenUsageSource };
|
|
1398
|
+
export { ConsoleTelemetrySink, GEN_AI_CONVERSATION_ID, GEN_AI_INPUT_TOKEN_KEYS, GEN_AI_MODEL_KEYS, GEN_AI_OPERATION_NAME, GEN_AI_OUTPUT_TOKEN_KEYS, GEN_AI_REQUEST_MODEL, GEN_AI_RESPONSE_MODEL, GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, HttpTelemetrySink, LangfuseSink, MultiTelemetrySink, ORCHESTRATOR_HOP_ID_HEADER, OtelTelemetrySink, PROVISION_TRACE_ID_HEADER, PTID_PREFIX, SSEChunkParser, SpanRecorder, StreamUsageExtractor, TOKEN_USAGE_COST_KEYS, TOKEN_USAGE_INPUT_KEYS, TOKEN_USAGE_OUTPUT_KEYS, TestTelemetrySink, TraceCollector, addTokenUsage, consumeSSEStream, createConsoleSink, createEmptyContext, createHttpSink, createLangfuseSinkFromEnv, createOtelSink, createOtelSinkFromEnv, createStreamUsageExtractor, createTestSink, createTraceCollector, createUsageCallback, firstTokenCount, firstUsageCostUsd, genAiUsageAttributes, initOtelProvider, isAdoptablePtid, isBuildResultEvent, isCompletionEvent, isCustomEvent, isDiagnosticEvent, isEnvironmentEvent, isErrorEvent, isFileChangeEvent, isFilePart, isMessagePartUpdatedEvent, isMessageUpdatedEvent, isReasoningPart, isTestResultEvent, isTextPart, isToolPart, mintPtid, monotonicNs, parseMetadataBlob, parseSSEData, parseSSEStream, parseServerTiming, readOrMintPtid, readTokenCostUsd, readTokenUsage, shutdownOtelProvider, spanDurationMs, sseToSignal, sseToTraceEvent, tokenCount, tokenUsageSource };
|
|
2114
1399
|
|
|
2115
1400
|
//# sourceMappingURL=index.mjs.map
|