@diogonzafe/tokenwatch 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters.cjs +16 -6
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.d.cts +2 -1
- package/dist/adapters.d.ts +2 -1
- package/dist/adapters.js +16 -6
- package/dist/adapters.js.map +1 -1
- package/dist/cli.js +114 -11
- package/dist/cli.js.map +1 -1
- package/dist/exporters.d.cts +1 -1
- package/dist/exporters.d.ts +1 -1
- package/dist/{index-fD5QLTWg.d.cts → index-B5OF0YCl.d.cts} +9 -0
- package/dist/{index-fD5QLTWg.d.ts → index-B5OF0YCl.d.ts} +9 -0
- package/dist/index.cjs +57 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +57 -27
- package/dist/index.js.map +1 -1
- package/dist/langchain.d.cts +1 -1
- package/dist/langchain.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TrackerConfig, a as Tracker, L as LazyTracker, b as TrackingMeta } from './index-
|
|
2
|
-
export { A as AnomalyDetectionConfig, B as BudgetConfig, C as CostForecast, F as FeatureStats, c as ForecastOptions, I as IExporter, d as IStorage, M as ModelPrice, e as ModelStats, P as PriceMap, f as PricesFile, R as Report, g as ReportOptions, S as SessionStats, U as UsageEntry, h as UserStats } from './index-
|
|
1
|
+
import { T as TrackerConfig, a as Tracker, L as LazyTracker, b as TrackingMeta } from './index-B5OF0YCl.cjs';
|
|
2
|
+
export { A as AnomalyDetectionConfig, B as BudgetConfig, C as CostForecast, F as FeatureStats, c as ForecastOptions, I as IExporter, d as IStorage, M as ModelPrice, e as ModelStats, P as PriceMap, f as PricesFile, R as Report, g as ReportOptions, S as SessionStats, U as UsageEntry, h as UserStats } from './index-B5OF0YCl.cjs';
|
|
3
3
|
|
|
4
4
|
declare function createTracker(config?: TrackerConfig): Tracker;
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TrackerConfig, a as Tracker, L as LazyTracker, b as TrackingMeta } from './index-
|
|
2
|
-
export { A as AnomalyDetectionConfig, B as BudgetConfig, C as CostForecast, F as FeatureStats, c as ForecastOptions, I as IExporter, d as IStorage, M as ModelPrice, e as ModelStats, P as PriceMap, f as PricesFile, R as Report, g as ReportOptions, S as SessionStats, U as UsageEntry, h as UserStats } from './index-
|
|
1
|
+
import { T as TrackerConfig, a as Tracker, L as LazyTracker, b as TrackingMeta } from './index-B5OF0YCl.js';
|
|
2
|
+
export { A as AnomalyDetectionConfig, B as BudgetConfig, C as CostForecast, F as FeatureStats, c as ForecastOptions, I as IExporter, d as IStorage, M as ModelPrice, e as ModelStats, P as PriceMap, f as PricesFile, R as Report, g as ReportOptions, S as SessionStats, U as UsageEntry, h as UserStats } from './index-B5OF0YCl.js';
|
|
3
3
|
|
|
4
4
|
declare function createTracker(config?: TrackerConfig): Tracker;
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -60,6 +60,7 @@ var CloudExporter = class {
|
|
|
60
60
|
sessionId: entry.sessionId,
|
|
61
61
|
userId: entry.userId,
|
|
62
62
|
feature: entry.feature,
|
|
63
|
+
metadata: entry.metadata,
|
|
63
64
|
timestamp: entry.timestamp
|
|
64
65
|
})
|
|
65
66
|
}).catch(() => {
|
|
@@ -157,6 +158,7 @@ var SqliteStorage = class {
|
|
|
157
158
|
user_id TEXT,
|
|
158
159
|
feature TEXT,
|
|
159
160
|
app_id TEXT,
|
|
161
|
+
metadata TEXT,
|
|
160
162
|
timestamp TEXT NOT NULL
|
|
161
163
|
)
|
|
162
164
|
`);
|
|
@@ -176,13 +178,16 @@ var SqliteStorage = class {
|
|
|
176
178
|
if (!cols.includes("app_id")) {
|
|
177
179
|
this.db.exec(`ALTER TABLE usage ADD COLUMN app_id TEXT`);
|
|
178
180
|
}
|
|
181
|
+
if (!cols.includes("metadata")) {
|
|
182
|
+
this.db.exec(`ALTER TABLE usage ADD COLUMN metadata TEXT`);
|
|
183
|
+
}
|
|
179
184
|
}
|
|
180
185
|
record(entry) {
|
|
181
186
|
this.db.prepare(
|
|
182
187
|
`INSERT INTO usage
|
|
183
188
|
(model, input_tokens, output_tokens, reasoning_tokens, cached_tokens, cache_creation_tokens,
|
|
184
|
-
cost_usd, session_id, user_id, feature, app_id, timestamp)
|
|
185
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
189
|
+
cost_usd, session_id, user_id, feature, app_id, metadata, timestamp)
|
|
190
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
186
191
|
).run(
|
|
187
192
|
entry.model,
|
|
188
193
|
entry.inputTokens,
|
|
@@ -195,6 +200,7 @@ var SqliteStorage = class {
|
|
|
195
200
|
entry.userId ?? null,
|
|
196
201
|
entry.feature ?? null,
|
|
197
202
|
entry.appId ?? null,
|
|
203
|
+
entry.metadata != null ? JSON.stringify(entry.metadata) : null,
|
|
198
204
|
entry.timestamp
|
|
199
205
|
);
|
|
200
206
|
}
|
|
@@ -212,6 +218,7 @@ var SqliteStorage = class {
|
|
|
212
218
|
...r.user_id != null && { userId: r.user_id },
|
|
213
219
|
...r.feature != null && { feature: r.feature },
|
|
214
220
|
...r.app_id != null && { appId: r.app_id },
|
|
221
|
+
...r.metadata != null && { metadata: JSON.parse(r.metadata) },
|
|
215
222
|
timestamp: r.timestamp
|
|
216
223
|
}));
|
|
217
224
|
}
|
|
@@ -1899,6 +1906,7 @@ ${issues}`);
|
|
|
1899
1906
|
const byUser = {};
|
|
1900
1907
|
const byFeature = {};
|
|
1901
1908
|
const byApp = {};
|
|
1909
|
+
const byMetadata = {};
|
|
1902
1910
|
let totalInput = 0;
|
|
1903
1911
|
let totalOutput = 0;
|
|
1904
1912
|
let totalCost = 0;
|
|
@@ -1940,6 +1948,14 @@ ${issues}`);
|
|
|
1940
1948
|
a.costUSD += e.costUSD;
|
|
1941
1949
|
a.calls += 1;
|
|
1942
1950
|
}
|
|
1951
|
+
if (e.metadata) {
|
|
1952
|
+
for (const [key, val] of Object.entries(e.metadata)) {
|
|
1953
|
+
const group = byMetadata[key] ??= {};
|
|
1954
|
+
const slot = group[val] ??= { costUSD: 0, calls: 0 };
|
|
1955
|
+
slot.costUSD += e.costUSD;
|
|
1956
|
+
slot.calls += 1;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1943
1959
|
}
|
|
1944
1960
|
if (options && entries.length > 0) {
|
|
1945
1961
|
periodFrom = entries[0]?.timestamp ?? periodFrom;
|
|
@@ -1952,6 +1968,7 @@ ${issues}`);
|
|
|
1952
1968
|
byUser,
|
|
1953
1969
|
byFeature,
|
|
1954
1970
|
byApp,
|
|
1971
|
+
byMetadata,
|
|
1955
1972
|
period: { from: periodFrom, to: lastTimestamp },
|
|
1956
1973
|
...pricesUpdatedAt ? { pricesUpdatedAt } : {}
|
|
1957
1974
|
};
|
|
@@ -2056,7 +2073,7 @@ ${issues}`);
|
|
|
2056
2073
|
}
|
|
2057
2074
|
async function exportCSV() {
|
|
2058
2075
|
const entries = await Promise.resolve(storage.getAll());
|
|
2059
|
-
const header = "timestamp,model,inputTokens,outputTokens,reasoningTokens,cachedTokens,cacheCreationTokens,costUSD,sessionId,userId,feature,appId";
|
|
2076
|
+
const header = "timestamp,model,inputTokens,outputTokens,reasoningTokens,cachedTokens,cacheCreationTokens,costUSD,sessionId,userId,feature,appId,metadata";
|
|
2060
2077
|
const rows = entries.map(
|
|
2061
2078
|
(e) => [
|
|
2062
2079
|
csvEscape(e.timestamp),
|
|
@@ -2070,7 +2087,8 @@ ${issues}`);
|
|
|
2070
2087
|
csvEscape(e.sessionId ?? ""),
|
|
2071
2088
|
csvEscape(e.userId ?? ""),
|
|
2072
2089
|
csvEscape(e.feature ?? ""),
|
|
2073
|
-
csvEscape(e.appId ?? "")
|
|
2090
|
+
csvEscape(e.appId ?? ""),
|
|
2091
|
+
csvEscape(e.metadata ? JSON.stringify(e.metadata) : "")
|
|
2074
2092
|
].join(",")
|
|
2075
2093
|
);
|
|
2076
2094
|
return [header, ...rows].join("\n");
|
|
@@ -2142,6 +2160,7 @@ function emptyReport() {
|
|
|
2142
2160
|
byUser: {},
|
|
2143
2161
|
byFeature: {},
|
|
2144
2162
|
byApp: {},
|
|
2163
|
+
byMetadata: {},
|
|
2145
2164
|
period: { from: now, to: now }
|
|
2146
2165
|
};
|
|
2147
2166
|
}
|
|
@@ -2198,12 +2217,13 @@ function createLazyTracker() {
|
|
|
2198
2217
|
|
|
2199
2218
|
// src/providers/openai.ts
|
|
2200
2219
|
function extractMeta(params) {
|
|
2201
|
-
const { __sessionId, __userId, __feature, ...cleaned } = params;
|
|
2220
|
+
const { __sessionId, __userId, __feature, __metadata, ...cleaned } = params;
|
|
2202
2221
|
return {
|
|
2203
2222
|
cleaned,
|
|
2204
2223
|
sessionId: typeof __sessionId === "string" ? __sessionId : void 0,
|
|
2205
2224
|
userId: typeof __userId === "string" ? __userId : void 0,
|
|
2206
|
-
feature: typeof __feature === "string" ? __feature : void 0
|
|
2225
|
+
feature: typeof __feature === "string" ? __feature : void 0,
|
|
2226
|
+
metadata: __metadata != null && typeof __metadata === "object" ? __metadata : void 0
|
|
2207
2227
|
};
|
|
2208
2228
|
}
|
|
2209
2229
|
function extractUsage(usage) {
|
|
@@ -2218,7 +2238,7 @@ function extractUsage(usage) {
|
|
|
2218
2238
|
cachedTokens
|
|
2219
2239
|
};
|
|
2220
2240
|
}
|
|
2221
|
-
function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0) {
|
|
2241
|
+
function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, metadata) {
|
|
2222
2242
|
tracker.track({
|
|
2223
2243
|
model,
|
|
2224
2244
|
inputTokens,
|
|
@@ -2227,10 +2247,11 @@ function trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningToken
|
|
|
2227
2247
|
...cachedTokens > 0 && { cachedTokens },
|
|
2228
2248
|
...sessionId !== void 0 && { sessionId },
|
|
2229
2249
|
...userId !== void 0 && { userId },
|
|
2230
|
-
...feature !== void 0 && { feature }
|
|
2250
|
+
...feature !== void 0 && { feature },
|
|
2251
|
+
...metadata !== void 0 && { metadata }
|
|
2231
2252
|
});
|
|
2232
2253
|
}
|
|
2233
|
-
async function* wrapStream(stream, model, sessionId, userId, feature, tracker) {
|
|
2254
|
+
async function* wrapStream(stream, model, sessionId, userId, feature, tracker, metadata) {
|
|
2234
2255
|
let lastChunk;
|
|
2235
2256
|
for await (const chunk of stream) {
|
|
2236
2257
|
lastChunk = chunk;
|
|
@@ -2242,7 +2263,7 @@ async function* wrapStream(stream, model, sessionId, userId, feature, tracker) {
|
|
|
2242
2263
|
`[tokenwatch] No usage data in stream for model "${model}". Cost recorded as $0. Pass stream_options: { include_usage: true } to get accurate costs.`
|
|
2243
2264
|
);
|
|
2244
2265
|
}
|
|
2245
|
-
trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens);
|
|
2266
|
+
trackWithMeta(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, metadata);
|
|
2246
2267
|
}
|
|
2247
2268
|
function wrapOpenAI(client, tracker) {
|
|
2248
2269
|
const proxiedCompletions = new Proxy(client.chat.completions, {
|
|
@@ -2250,7 +2271,7 @@ function wrapOpenAI(client, tracker) {
|
|
|
2250
2271
|
if (prop !== "create")
|
|
2251
2272
|
return target[prop];
|
|
2252
2273
|
return async function(params) {
|
|
2253
|
-
const { cleaned, sessionId, userId, feature } = extractMeta(params);
|
|
2274
|
+
const { cleaned, sessionId, userId, feature, metadata } = extractMeta(params);
|
|
2254
2275
|
const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
|
|
2255
2276
|
const result = await target.create(cleaned);
|
|
2256
2277
|
if (result && typeof result === "object" && Symbol.asyncIterator in result) {
|
|
@@ -2260,7 +2281,8 @@ function wrapOpenAI(client, tracker) {
|
|
|
2260
2281
|
sessionId,
|
|
2261
2282
|
userId,
|
|
2262
2283
|
feature,
|
|
2263
|
-
tracker
|
|
2284
|
+
tracker,
|
|
2285
|
+
metadata
|
|
2264
2286
|
);
|
|
2265
2287
|
}
|
|
2266
2288
|
const completion = result;
|
|
@@ -2274,7 +2296,8 @@ function wrapOpenAI(client, tracker) {
|
|
|
2274
2296
|
sessionId,
|
|
2275
2297
|
userId,
|
|
2276
2298
|
feature,
|
|
2277
|
-
cachedTokens
|
|
2299
|
+
cachedTokens,
|
|
2300
|
+
metadata
|
|
2278
2301
|
);
|
|
2279
2302
|
return result;
|
|
2280
2303
|
};
|
|
@@ -2291,12 +2314,12 @@ function wrapOpenAI(client, tracker) {
|
|
|
2291
2314
|
if (prop !== "create")
|
|
2292
2315
|
return target[prop];
|
|
2293
2316
|
return async function(params) {
|
|
2294
|
-
const { cleaned, sessionId, userId, feature } = extractMeta(params);
|
|
2317
|
+
const { cleaned, sessionId, userId, feature, metadata } = extractMeta(params);
|
|
2295
2318
|
const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
|
|
2296
2319
|
const result = await target.create(cleaned);
|
|
2297
2320
|
const embedding = result;
|
|
2298
2321
|
const inputTokens = embedding.usage?.total_tokens ?? 0;
|
|
2299
|
-
trackWithMeta(tracker, embedding.model ?? model, inputTokens, 0, 0, sessionId, userId, feature);
|
|
2322
|
+
trackWithMeta(tracker, embedding.model ?? model, inputTokens, 0, 0, sessionId, userId, feature, 0, metadata);
|
|
2300
2323
|
return result;
|
|
2301
2324
|
};
|
|
2302
2325
|
}
|
|
@@ -2312,12 +2335,13 @@ function wrapOpenAI(client, tracker) {
|
|
|
2312
2335
|
|
|
2313
2336
|
// src/providers/anthropic.ts
|
|
2314
2337
|
function extractMeta2(params) {
|
|
2315
|
-
const { __sessionId, __userId, __feature, ...cleaned } = params;
|
|
2338
|
+
const { __sessionId, __userId, __feature, __metadata, ...cleaned } = params;
|
|
2316
2339
|
return {
|
|
2317
2340
|
cleaned,
|
|
2318
2341
|
sessionId: typeof __sessionId === "string" ? __sessionId : void 0,
|
|
2319
2342
|
userId: typeof __userId === "string" ? __userId : void 0,
|
|
2320
|
-
feature: typeof __feature === "string" ? __feature : void 0
|
|
2343
|
+
feature: typeof __feature === "string" ? __feature : void 0,
|
|
2344
|
+
metadata: __metadata != null && typeof __metadata === "object" ? __metadata : void 0
|
|
2321
2345
|
};
|
|
2322
2346
|
}
|
|
2323
2347
|
function extractUsage2(usage) {
|
|
@@ -2334,7 +2358,7 @@ function extractThinkingTokenApprox(content) {
|
|
|
2334
2358
|
const chars = content.filter((b) => b.type === "thinking").reduce((sum, b) => sum + (b.thinking?.length ?? 0), 0);
|
|
2335
2359
|
return chars > 0 ? Math.round(chars / 4) : 0;
|
|
2336
2360
|
}
|
|
2337
|
-
function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, cacheCreationTokens = 0) {
|
|
2361
|
+
function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens = 0, cacheCreationTokens = 0, metadata) {
|
|
2338
2362
|
tracker.track({
|
|
2339
2363
|
model,
|
|
2340
2364
|
inputTokens,
|
|
@@ -2344,10 +2368,11 @@ function trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningToke
|
|
|
2344
2368
|
...cacheCreationTokens > 0 && { cacheCreationTokens },
|
|
2345
2369
|
...sessionId !== void 0 && { sessionId },
|
|
2346
2370
|
...userId !== void 0 && { userId },
|
|
2347
|
-
...feature !== void 0 && { feature }
|
|
2371
|
+
...feature !== void 0 && { feature },
|
|
2372
|
+
...metadata !== void 0 && { metadata }
|
|
2348
2373
|
});
|
|
2349
2374
|
}
|
|
2350
|
-
async function* wrapStream2(stream, model, sessionId, userId, feature, tracker) {
|
|
2375
|
+
async function* wrapStream2(stream, model, sessionId, userId, feature, tracker, metadata) {
|
|
2351
2376
|
let inputTokens = 0;
|
|
2352
2377
|
let outputTokens = 0;
|
|
2353
2378
|
let cachedTokens = 0;
|
|
@@ -2375,7 +2400,7 @@ async function* wrapStream2(stream, model, sessionId, userId, feature, tracker)
|
|
|
2375
2400
|
}
|
|
2376
2401
|
}
|
|
2377
2402
|
const reasoningTokens = thinkingCharCount > 0 ? Math.round(thinkingCharCount / 4) : 0;
|
|
2378
|
-
trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, cacheCreationTokens);
|
|
2403
|
+
trackWithMeta2(tracker, model, inputTokens, outputTokens, reasoningTokens, sessionId, userId, feature, cachedTokens, cacheCreationTokens, metadata);
|
|
2379
2404
|
}
|
|
2380
2405
|
function wrapAnthropic(client, tracker) {
|
|
2381
2406
|
const proxiedMessages = new Proxy(client.messages, {
|
|
@@ -2383,7 +2408,7 @@ function wrapAnthropic(client, tracker) {
|
|
|
2383
2408
|
if (prop !== "create")
|
|
2384
2409
|
return target[prop];
|
|
2385
2410
|
return async function(params) {
|
|
2386
|
-
const { cleaned, sessionId, userId, feature } = extractMeta2(params);
|
|
2411
|
+
const { cleaned, sessionId, userId, feature, metadata } = extractMeta2(params);
|
|
2387
2412
|
const model = typeof cleaned["model"] === "string" ? cleaned["model"] : "unknown";
|
|
2388
2413
|
const result = await target.create(cleaned);
|
|
2389
2414
|
if (result && typeof result === "object" && Symbol.asyncIterator in result) {
|
|
@@ -2393,7 +2418,8 @@ function wrapAnthropic(client, tracker) {
|
|
|
2393
2418
|
sessionId,
|
|
2394
2419
|
userId,
|
|
2395
2420
|
feature,
|
|
2396
|
-
tracker
|
|
2421
|
+
tracker,
|
|
2422
|
+
metadata
|
|
2397
2423
|
);
|
|
2398
2424
|
}
|
|
2399
2425
|
const message = result;
|
|
@@ -2409,7 +2435,8 @@ function wrapAnthropic(client, tracker) {
|
|
|
2409
2435
|
userId,
|
|
2410
2436
|
feature,
|
|
2411
2437
|
cachedTokens,
|
|
2412
|
-
cacheCreationTokens
|
|
2438
|
+
cacheCreationTokens,
|
|
2439
|
+
metadata
|
|
2413
2440
|
);
|
|
2414
2441
|
return result;
|
|
2415
2442
|
};
|
|
@@ -2430,10 +2457,11 @@ function wrapGemini(client, tracker) {
|
|
|
2430
2457
|
if (prop !== "getGenerativeModel")
|
|
2431
2458
|
return target[prop];
|
|
2432
2459
|
return function(modelParams) {
|
|
2433
|
-
const { __sessionId, __userId, __feature, ...cleanedParams } = modelParams;
|
|
2460
|
+
const { __sessionId, __userId, __feature, __metadata, ...cleanedParams } = modelParams;
|
|
2434
2461
|
const feature = typeof __feature === "string" ? __feature : void 0;
|
|
2435
2462
|
const sessionId = typeof __sessionId === "string" ? __sessionId : void 0;
|
|
2436
2463
|
const userId = typeof __userId === "string" ? __userId : void 0;
|
|
2464
|
+
const metadata = __metadata != null && typeof __metadata === "object" ? __metadata : void 0;
|
|
2437
2465
|
const modelInstance = target.getGenerativeModel(cleanedParams);
|
|
2438
2466
|
const modelId = modelParams.model;
|
|
2439
2467
|
return new Proxy(modelInstance, {
|
|
@@ -2448,7 +2476,8 @@ function wrapGemini(client, tracker) {
|
|
|
2448
2476
|
outputTokens: meta?.candidatesTokenCount ?? 0,
|
|
2449
2477
|
...sessionId !== void 0 && { sessionId },
|
|
2450
2478
|
...userId !== void 0 && { userId },
|
|
2451
|
-
...feature !== void 0 && { feature }
|
|
2479
|
+
...feature !== void 0 && { feature },
|
|
2480
|
+
...metadata !== void 0 && { metadata }
|
|
2452
2481
|
});
|
|
2453
2482
|
return result;
|
|
2454
2483
|
};
|
|
@@ -2464,7 +2493,8 @@ function wrapGemini(client, tracker) {
|
|
|
2464
2493
|
outputTokens: meta?.candidatesTokenCount ?? 0,
|
|
2465
2494
|
...sessionId !== void 0 && { sessionId },
|
|
2466
2495
|
...userId !== void 0 && { userId },
|
|
2467
|
-
...feature !== void 0 && { feature }
|
|
2496
|
+
...feature !== void 0 && { feature },
|
|
2497
|
+
...metadata !== void 0 && { metadata }
|
|
2468
2498
|
});
|
|
2469
2499
|
}).catch(() => {
|
|
2470
2500
|
});
|