@rawdash/connector-anthropic 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/index.d.ts +76 -2
- package/dist/index.js +75 -50
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -37,31 +37,32 @@ Authenticates with an Anthropic organization admin API key (sk-ant-admin-). Admi
|
|
|
37
37
|
- Endpoint: `GET /v1/organizations/usage_report/messages`
|
|
38
38
|
- Unit: tokens
|
|
39
39
|
- Granularity: daily
|
|
40
|
-
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`
|
|
40
|
+
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`, `account_id`, `service_account_id`
|
|
41
41
|
- Sample value is uncached_input_tokens. Cache-read and cache-creation token volumes are mirrored on their own metrics so a cache hit ratio can be computed at query time.
|
|
42
42
|
- **`anthropic_output_tokens`** _(metric)_ - Daily output tokens generated by the Anthropic Messages API, grouped by model and workspace.
|
|
43
43
|
- Endpoint: `GET /v1/organizations/usage_report/messages`
|
|
44
44
|
- Unit: tokens
|
|
45
45
|
- Granularity: daily
|
|
46
|
-
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`
|
|
46
|
+
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`, `account_id`, `service_account_id`
|
|
47
47
|
- Written alongside anthropic_input_tokens from the same usage_messages API call.
|
|
48
48
|
- **`anthropic_cache_read_tokens`** _(metric)_ - Daily input tokens read from the prompt cache, grouped by model and workspace.
|
|
49
49
|
- Endpoint: `GET /v1/organizations/usage_report/messages`
|
|
50
50
|
- Unit: tokens
|
|
51
51
|
- Granularity: daily
|
|
52
|
-
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`
|
|
52
|
+
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`, `account_id`, `service_account_id`
|
|
53
53
|
- Cache hits are charged at a fraction of the uncached rate, so this metric paired with anthropic_input_tokens gives the cache hit ratio.
|
|
54
54
|
- **`anthropic_cache_creation_tokens`** _(metric)_ - Daily input tokens written into the prompt cache (sum of the 1h and 5m ephemeral caches), grouped by model and workspace.
|
|
55
55
|
- Endpoint: `GET /v1/organizations/usage_report/messages`
|
|
56
56
|
- Unit: tokens
|
|
57
57
|
- Granularity: daily
|
|
58
|
-
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`
|
|
59
|
-
-
|
|
58
|
+
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`, `account_id`, `service_account_id`
|
|
59
|
+
- Measures: `ephemeral_1h_input_tokens`, `ephemeral_5m_input_tokens`
|
|
60
|
+
- The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are declared measures for finer-grained widgets.
|
|
60
61
|
- **`anthropic_web_search_requests`** _(metric)_ - Daily count of web-search tool requests executed server-side by Claude, grouped by model and workspace.
|
|
61
62
|
- Endpoint: `GET /v1/organizations/usage_report/messages`
|
|
62
63
|
- Unit: requests
|
|
63
64
|
- Granularity: daily
|
|
64
|
-
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`
|
|
65
|
+
- Dimensions: `model`, `workspace_id`, `api_key_id`, `service_tier`, `context_window`, `inference_geo`, `account_id`, `service_account_id`
|
|
65
66
|
- Sourced from server_tool_use.web_search_requests on each usage bucket. Zero rows are still written so a "no usage today" widget renders correctly.
|
|
66
67
|
- **`anthropic_cost_usd`** _(metric)_ - Daily organization spend in USD, broken down by workspace and cost line item, pulled from the Anthropic Cost Report.
|
|
67
68
|
- Endpoint: `GET /v1/organizations/cost_report`
|
package/dist/index.d.ts
CHANGED
|
@@ -86,6 +86,12 @@ declare const anthropicResources: {
|
|
|
86
86
|
}, {
|
|
87
87
|
readonly name: "inference_geo";
|
|
88
88
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
89
|
+
}, {
|
|
90
|
+
readonly name: "account_id";
|
|
91
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
92
|
+
}, {
|
|
93
|
+
readonly name: "service_account_id";
|
|
94
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
89
95
|
}];
|
|
90
96
|
readonly notes: "Sample value is uncached_input_tokens. Cache-read and cache-creation token volumes are mirrored on their own metrics so a cache hit ratio can be computed at query time.";
|
|
91
97
|
readonly responses: {
|
|
@@ -143,6 +149,12 @@ declare const anthropicResources: {
|
|
|
143
149
|
}, {
|
|
144
150
|
readonly name: "inference_geo";
|
|
145
151
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
152
|
+
}, {
|
|
153
|
+
readonly name: "account_id";
|
|
154
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
155
|
+
}, {
|
|
156
|
+
readonly name: "service_account_id";
|
|
157
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
146
158
|
}];
|
|
147
159
|
readonly notes: "Written alongside anthropic_input_tokens from the same usage_messages API call.";
|
|
148
160
|
};
|
|
@@ -170,6 +182,12 @@ declare const anthropicResources: {
|
|
|
170
182
|
}, {
|
|
171
183
|
readonly name: "inference_geo";
|
|
172
184
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
185
|
+
}, {
|
|
186
|
+
readonly name: "account_id";
|
|
187
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
188
|
+
}, {
|
|
189
|
+
readonly name: "service_account_id";
|
|
190
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
173
191
|
}];
|
|
174
192
|
readonly notes: "Cache hits are charged at a fraction of the uncached rate, so this metric paired with anthropic_input_tokens gives the cache hit ratio.";
|
|
175
193
|
};
|
|
@@ -197,8 +215,21 @@ declare const anthropicResources: {
|
|
|
197
215
|
}, {
|
|
198
216
|
readonly name: "inference_geo";
|
|
199
217
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
218
|
+
}, {
|
|
219
|
+
readonly name: "account_id";
|
|
220
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
221
|
+
}, {
|
|
222
|
+
readonly name: "service_account_id";
|
|
223
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
224
|
+
}];
|
|
225
|
+
readonly measures: [{
|
|
226
|
+
readonly name: "ephemeral_1h_input_tokens";
|
|
227
|
+
readonly description: "Input tokens written into the 1-hour ephemeral prompt cache (a component of the sample value).";
|
|
228
|
+
}, {
|
|
229
|
+
readonly name: "ephemeral_5m_input_tokens";
|
|
230
|
+
readonly description: "Input tokens written into the 5-minute ephemeral prompt cache (a component of the sample value).";
|
|
200
231
|
}];
|
|
201
|
-
readonly notes: "The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are
|
|
232
|
+
readonly notes: "The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are declared measures for finer-grained widgets.";
|
|
202
233
|
};
|
|
203
234
|
readonly anthropic_web_search_requests: {
|
|
204
235
|
readonly shape: "metric";
|
|
@@ -224,6 +255,12 @@ declare const anthropicResources: {
|
|
|
224
255
|
}, {
|
|
225
256
|
readonly name: "inference_geo";
|
|
226
257
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
258
|
+
}, {
|
|
259
|
+
readonly name: "account_id";
|
|
260
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
261
|
+
}, {
|
|
262
|
+
readonly name: "service_account_id";
|
|
263
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
227
264
|
}];
|
|
228
265
|
readonly notes: "Sourced from server_tool_use.web_search_requests on each usage bucket. Zero rows are still written so a \"no usage today\" widget renders correctly.";
|
|
229
266
|
};
|
|
@@ -336,6 +373,12 @@ declare class AnthropicConnector extends BaseConnector<AnthropicSettings, Anthro
|
|
|
336
373
|
}, {
|
|
337
374
|
readonly name: "inference_geo";
|
|
338
375
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
376
|
+
}, {
|
|
377
|
+
readonly name: "account_id";
|
|
378
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
379
|
+
}, {
|
|
380
|
+
readonly name: "service_account_id";
|
|
381
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
339
382
|
}];
|
|
340
383
|
readonly notes: "Sample value is uncached_input_tokens. Cache-read and cache-creation token volumes are mirrored on their own metrics so a cache hit ratio can be computed at query time.";
|
|
341
384
|
readonly responses: {
|
|
@@ -393,6 +436,12 @@ declare class AnthropicConnector extends BaseConnector<AnthropicSettings, Anthro
|
|
|
393
436
|
}, {
|
|
394
437
|
readonly name: "inference_geo";
|
|
395
438
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
439
|
+
}, {
|
|
440
|
+
readonly name: "account_id";
|
|
441
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
442
|
+
}, {
|
|
443
|
+
readonly name: "service_account_id";
|
|
444
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
396
445
|
}];
|
|
397
446
|
readonly notes: "Written alongside anthropic_input_tokens from the same usage_messages API call.";
|
|
398
447
|
};
|
|
@@ -420,6 +469,12 @@ declare class AnthropicConnector extends BaseConnector<AnthropicSettings, Anthro
|
|
|
420
469
|
}, {
|
|
421
470
|
readonly name: "inference_geo";
|
|
422
471
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
472
|
+
}, {
|
|
473
|
+
readonly name: "account_id";
|
|
474
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
475
|
+
}, {
|
|
476
|
+
readonly name: "service_account_id";
|
|
477
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
423
478
|
}];
|
|
424
479
|
readonly notes: "Cache hits are charged at a fraction of the uncached rate, so this metric paired with anthropic_input_tokens gives the cache hit ratio.";
|
|
425
480
|
};
|
|
@@ -447,8 +502,21 @@ declare class AnthropicConnector extends BaseConnector<AnthropicSettings, Anthro
|
|
|
447
502
|
}, {
|
|
448
503
|
readonly name: "inference_geo";
|
|
449
504
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
505
|
+
}, {
|
|
506
|
+
readonly name: "account_id";
|
|
507
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
508
|
+
}, {
|
|
509
|
+
readonly name: "service_account_id";
|
|
510
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
511
|
+
}];
|
|
512
|
+
readonly measures: [{
|
|
513
|
+
readonly name: "ephemeral_1h_input_tokens";
|
|
514
|
+
readonly description: "Input tokens written into the 1-hour ephemeral prompt cache (a component of the sample value).";
|
|
515
|
+
}, {
|
|
516
|
+
readonly name: "ephemeral_5m_input_tokens";
|
|
517
|
+
readonly description: "Input tokens written into the 5-minute ephemeral prompt cache (a component of the sample value).";
|
|
450
518
|
}];
|
|
451
|
-
readonly notes: "The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are
|
|
519
|
+
readonly notes: "The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are declared measures for finer-grained widgets.";
|
|
452
520
|
};
|
|
453
521
|
readonly anthropic_web_search_requests: {
|
|
454
522
|
readonly shape: "metric";
|
|
@@ -474,6 +542,12 @@ declare class AnthropicConnector extends BaseConnector<AnthropicSettings, Anthro
|
|
|
474
542
|
}, {
|
|
475
543
|
readonly name: "inference_geo";
|
|
476
544
|
readonly description: "Inference geo the request ran in (global, us, not_available), or null.";
|
|
545
|
+
}, {
|
|
546
|
+
readonly name: "account_id";
|
|
547
|
+
readonly description: "Account id the usage is attributed to (or null).";
|
|
548
|
+
}, {
|
|
549
|
+
readonly name: "service_account_id";
|
|
550
|
+
readonly description: "Service account id the usage is attributed to (or null).";
|
|
477
551
|
}];
|
|
478
552
|
readonly notes: "Sourced from server_tool_use.web_search_requests on each usage bucket. Zero rows are still written so a \"no usage today\" widget renders correctly.";
|
|
479
553
|
};
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
defineConnectorDoc,
|
|
34
34
|
defineResources,
|
|
35
35
|
makeChunkedCursorGuard,
|
|
36
|
+
metricSample,
|
|
36
37
|
schemasFromResources,
|
|
37
38
|
selectActivePhases
|
|
38
39
|
} from "@rawdash/core";
|
|
@@ -195,6 +196,14 @@ var USAGE_DIMENSIONS = [
|
|
|
195
196
|
{
|
|
196
197
|
name: "inference_geo",
|
|
197
198
|
description: "Inference geo the request ran in (global, us, not_available), or null."
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: "account_id",
|
|
202
|
+
description: "Account id the usage is attributed to (or null)."
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "service_account_id",
|
|
206
|
+
description: "Service account id the usage is attributed to (or null)."
|
|
198
207
|
}
|
|
199
208
|
];
|
|
200
209
|
var COST_DIMENSIONS = [
|
|
@@ -267,7 +276,17 @@ var anthropicResources = defineResources({
|
|
|
267
276
|
unit: "tokens",
|
|
268
277
|
granularity: "daily",
|
|
269
278
|
dimensions: [...USAGE_DIMENSIONS],
|
|
270
|
-
|
|
279
|
+
measures: [
|
|
280
|
+
{
|
|
281
|
+
name: "ephemeral_1h_input_tokens",
|
|
282
|
+
description: "Input tokens written into the 1-hour ephemeral prompt cache (a component of the sample value)."
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: "ephemeral_5m_input_tokens",
|
|
286
|
+
description: "Input tokens written into the 5-minute ephemeral prompt cache (a component of the sample value)."
|
|
287
|
+
}
|
|
288
|
+
],
|
|
289
|
+
notes: "The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are declared measures for finer-grained widgets."
|
|
271
290
|
},
|
|
272
291
|
anthropic_web_search_requests: {
|
|
273
292
|
shape: "metric",
|
|
@@ -365,40 +384,45 @@ function buildUsageSamples(buckets) {
|
|
|
365
384
|
for (const row of bucket.results) {
|
|
366
385
|
const common = usageDimensionAttributes(row);
|
|
367
386
|
const cacheCreation = row.cache_creation;
|
|
368
|
-
inputTokens.push(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
387
|
+
inputTokens.push(
|
|
388
|
+
metricSample(anthropicResources, "anthropic_input_tokens", {
|
|
389
|
+
ts,
|
|
390
|
+
value: row.uncached_input_tokens,
|
|
391
|
+
attributes: { ...common }
|
|
392
|
+
})
|
|
393
|
+
);
|
|
394
|
+
outputTokens.push(
|
|
395
|
+
metricSample(anthropicResources, "anthropic_output_tokens", {
|
|
396
|
+
ts,
|
|
397
|
+
value: row.output_tokens,
|
|
398
|
+
attributes: { ...common }
|
|
399
|
+
})
|
|
400
|
+
);
|
|
401
|
+
cacheReadTokens.push(
|
|
402
|
+
metricSample(anthropicResources, "anthropic_cache_read_tokens", {
|
|
403
|
+
ts,
|
|
404
|
+
value: row.cache_read_input_tokens,
|
|
405
|
+
attributes: { ...common }
|
|
406
|
+
})
|
|
407
|
+
);
|
|
408
|
+
cacheCreationTokens.push(
|
|
409
|
+
metricSample(anthropicResources, "anthropic_cache_creation_tokens", {
|
|
410
|
+
ts,
|
|
411
|
+
value: cacheCreationTotal(row),
|
|
412
|
+
attributes: {
|
|
413
|
+
...common,
|
|
414
|
+
ephemeral_1h_input_tokens: cacheCreation?.ephemeral_1h_input_tokens ?? 0,
|
|
415
|
+
ephemeral_5m_input_tokens: cacheCreation?.ephemeral_5m_input_tokens ?? 0
|
|
416
|
+
}
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
webSearchRequests.push(
|
|
420
|
+
metricSample(anthropicResources, "anthropic_web_search_requests", {
|
|
421
|
+
ts,
|
|
422
|
+
value: row.server_tool_use?.web_search_requests ?? 0,
|
|
423
|
+
attributes: { ...common }
|
|
424
|
+
})
|
|
425
|
+
);
|
|
402
426
|
}
|
|
403
427
|
}
|
|
404
428
|
return {
|
|
@@ -419,21 +443,22 @@ function buildCostSamples(buckets) {
|
|
|
419
443
|
for (const row of bucket.results) {
|
|
420
444
|
const rawAmount = Number.parseFloat(row.amount);
|
|
421
445
|
const value = Number.isFinite(rawAmount) ? rawAmount / COST_AMOUNT_DIVISOR : 0;
|
|
422
|
-
samples.push(
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
446
|
+
samples.push(
|
|
447
|
+
metricSample(anthropicResources, "anthropic_cost_usd", {
|
|
448
|
+
ts,
|
|
449
|
+
value,
|
|
450
|
+
attributes: {
|
|
451
|
+
workspace_id: nullableString(row.workspace_id),
|
|
452
|
+
description: nullableString(row.description),
|
|
453
|
+
cost_type: nullableString(row.cost_type),
|
|
454
|
+
model: nullableString(row.model),
|
|
455
|
+
token_type: nullableString(row.token_type),
|
|
456
|
+
service_tier: nullableString(row.service_tier),
|
|
457
|
+
context_window: nullableString(row.context_window),
|
|
458
|
+
currency: row.currency
|
|
459
|
+
}
|
|
460
|
+
})
|
|
461
|
+
);
|
|
437
462
|
}
|
|
438
463
|
}
|
|
439
464
|
return samples;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../connector-shared/src/errors.ts","../../../connector-shared/src/retry.ts","../../../connector-shared/src/version.ts","../../../connector-shared/src/request.ts","../../../connector-shared/src/rate-limit.ts","../../../connector-shared/src/map-concurrent.ts","../../../connector-shared/src/sanitize.ts","../../../connector-shared/src/epoch.ts","../../../connector-shared/src/pagination.ts","../../../connector-shared/src/logger.ts","../src/anthropic.ts","../src/index.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n\nexport function connectorUserAgent(connectorId: string): string {\n return `rawdash-connector-${connectorId}/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n}\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport interface StandardRateLimitPolicyConfig {\n remainingHeader: string;\n resetHeader: string;\n resetUnit: 's' | 'ms';\n resetFallbackMs?: number;\n}\n\nexport function standardRateLimitPolicy(\n config: StandardRateLimitPolicyConfig,\n): RateLimitPolicy {\n const { remainingHeader, resetHeader, resetUnit, resetFallbackMs } = config;\n const multiplier = resetUnit === 's' ? 1000 : 1;\n return {\n parse(h) {\n const remainingRaw = h.get(remainingHeader);\n if (remainingRaw === null || remainingRaw.trim() === '') {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n const resetRaw = h.get(resetHeader);\n if (resetRaw === null) {\n if (resetFallbackMs === undefined) {\n return null;\n }\n return {\n remaining,\n resetAt: new Date(Date.now() + resetFallbackMs),\n };\n }\n if (resetRaw.trim() === '') {\n return null;\n }\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n const resetMs = reset * multiplier;\n if (!Number.isFinite(resetMs)) {\n return null;\n }\n return { remaining, resetAt: new Date(resetMs) };\n },\n };\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n if (items.length === 0) {\n return results;\n }\n const normalized = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const limit = Math.max(1, Math.min(normalized, items.length));\n let next = 0;\n let failed = false;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const i = next++;\n if (i >= items.length) {\n return;\n }\n try {\n results[i] = await fn(items[i]!, i);\n } catch (err) {\n failed = true;\n throw err;\n }\n }\n }\n\n const workers: Promise<void>[] = [];\n for (let w = 0; w < limit; w++) {\n workers.push(worker());\n }\n await Promise.all(workers);\n return results;\n}\n","export interface SanitizeAllowedUrlOptions {\n url: string | null;\n host: string;\n pathname: string;\n protocol?: 'https:' | 'http:';\n}\n\nexport function sanitizeAllowedUrl(\n options: SanitizeAllowedUrlOptions,\n): string | null {\n const { url, host, pathname, protocol = 'https:' } = options;\n if (url === null) {\n return null;\n }\n try {\n const u = new URL(url);\n if (u.protocol !== protocol || u.host !== host || u.pathname !== pathname) {\n return null;\n }\n return u.toString();\n } catch {\n return null;\n }\n}\n","export type EpochUnit = 'ms' | 's' | 'iso';\n\nexport function parseEpoch(\n value: number | string | null | undefined,\n unit: EpochUnit,\n): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (unit === 'iso') {\n if (typeof value !== 'string') {\n return null;\n }\n const ms = new Date(value).getTime();\n return Number.isFinite(ms) ? ms : null;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return null;\n }\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return null;\n }\n const result = unit === 's' ? n * 1000 : n;\n return Number.isFinite(result) ? result : null;\n}\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type LogFields = Record<string, unknown>;\n\nexport interface ConnectorLogger {\n info(event: string, fields?: LogFields): void;\n warn(event: string, fields?: LogFields): void;\n}\n\nexport interface ConnectorLoggerOptions {\n scope: string;\n}\n\nconst MAX_VALUE_LEN = 120;\n\nfunction truncate(s: string, max = MAX_VALUE_LEN): string {\n if (s.length <= max) {\n return s;\n }\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return '';\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'string') {\n const t = truncate(value);\n if (/[\\s\"=]/.test(t)) {\n return JSON.stringify(t);\n }\n return t;\n }\n if (typeof value === 'bigint') {\n return value.toString();\n }\n let json: string | undefined;\n try {\n json = JSON.stringify(value);\n } catch {\n json = undefined;\n }\n return truncate(json ?? String(value));\n}\n\nexport function formatLogFields(fields?: LogFields): string {\n if (!fields) {\n return '';\n }\n const parts: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v === undefined) {\n continue;\n }\n parts.push(`${k}=${formatValue(v)}`);\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nexport function formatLogLine(\n scope: string,\n event: string,\n fields?: LogFields,\n): string {\n return `[${scope}] ${event}${formatLogFields(fields)}`;\n}\n\nexport function createDefaultConnectorLogger(\n opts: ConnectorLoggerOptions,\n): ConnectorLogger {\n return {\n info(event, fields) {\n console.info(formatLogLine(opts.scope, event, fields));\n },\n warn(event, fields) {\n console.warn(formatLogLine(opts.scope, event, fields));\n },\n };\n}\n\nconst NOOP_LOGGER: ConnectorLogger = {\n info() {},\n warn() {},\n};\n\nexport function noopConnectorLogger(): ConnectorLogger {\n return NOOP_LOGGER;\n}\n","import {\n type HttpResponse,\n connectorUserAgent,\n parseEpoch,\n} from '@rawdash/connector-shared';\nimport {\n BaseConnector,\n type ConnectorContext,\n type ConnectorDoc,\n type CredentialsSchema,\n type JSONValue,\n type MetricSample,\n type StorageHandle,\n type SyncOptions,\n type SyncResult,\n defineConfigFields,\n defineConnectorDoc,\n defineResources,\n makeChunkedCursorGuard,\n schemasFromResources,\n selectActivePhases,\n} from '@rawdash/core';\nimport { z } from 'zod';\n\nconst ANTHROPIC_API_HOST = 'api.anthropic.com';\nconst ANTHROPIC_API_BASE = `https://${ANTHROPIC_API_HOST}`;\nconst ANTHROPIC_API_VERSION = '2023-06-01';\nconst USAGE_PAGE_LIMIT = 31;\nconst COSTS_PAGE_LIMIT = 31;\nconst MS_PER_DAY = 86_400_000;\nconst DEFAULT_LOOKBACK_DAYS = 30;\nconst INCREMENTAL_LOOKBACK_DAYS = 2;\n// Cost report `amount` is a decimal string in the lowest currency unit (cents\n// for USD): e.g. \"123.45\" represents $1.2345. Divide by 100 to get dollars.\nconst COST_AMOUNT_DIVISOR = 100;\n\nexport const configFields = defineConfigFields(\n z.object({\n adminApiKey: z.object({ $secret: z.string().min(1) }).meta({\n label: 'Admin API key',\n description:\n 'Anthropic organization admin API key (starts with sk-ant-admin-). Create one at console.anthropic.com -> Settings -> Admin keys. Regular API keys (sk-ant-api-) cannot read the Usage and Cost reports.',\n placeholder: 'ANTHROPIC_ADMIN_API_KEY',\n secret: true,\n }),\n workspaceIds: z.array(z.string().min(1)).nonempty().optional().meta({\n label: 'Workspace IDs (optional)',\n description:\n 'Restrict usage and cost queries to specific Anthropic workspace ids (wrkspc_...). Omit to aggregate every workspace the admin key can see.',\n }),\n resources: z\n .array(\n z.enum([\n 'anthropic_input_tokens',\n 'anthropic_output_tokens',\n 'anthropic_cache_read_tokens',\n 'anthropic_cache_creation_tokens',\n 'anthropic_web_search_requests',\n 'anthropic_cost_usd',\n ]),\n )\n .nonempty()\n .optional()\n .meta({\n label: 'Resources',\n description:\n 'Which Anthropic metric series to sync. Omit to sync all of them. The five usage metrics share one upstream call to the Messages Usage Report; enabling any one of them fetches the report and writes all five.',\n }),\n lookbackDays: z.number().int().positive().max(180).optional().meta({\n label: 'Backfill window (days)',\n description:\n 'How many days of usage history to fetch on a full sync. Defaults to 30. The Usage Report returns at most 31 buckets per page, so longer windows paginate.',\n placeholder: '30',\n }),\n }),\n);\n\nexport const doc: ConnectorDoc = defineConnectorDoc({\n displayName: 'Anthropic',\n category: 'engineering',\n brandColor: '#D97757',\n tagline:\n 'Track Anthropic spend, daily token usage across Claude models, cache hit volumes, and web-search tool requests from the Anthropic Admin API.',\n vendor: {\n name: 'Anthropic',\n domain: 'anthropic.com',\n apiDocs:\n 'https://docs.claude.com/en/api/admin-api/usage-cost/get-messages-usage-report',\n website: 'https://anthropic.com',\n },\n auth: {\n summary:\n 'Authenticates with an Anthropic organization admin API key (sk-ant-admin-). Admin keys are the only key class that can read the Usage and Cost reports; regular API keys return 403.',\n setup: [\n 'Open console.anthropic.com -> Settings -> Admin Keys and create a new admin key. Admin keys are organization-scoped, so create the key from the organization whose usage you want to read.',\n 'Store the key as a secret (e.g. ANTHROPIC_ADMIN_API_KEY).',\n 'Reference it from config as `adminApiKey: secret(\"ANTHROPIC_ADMIN_API_KEY\")`.',\n 'Optionally set `workspaceIds` to restrict the query to a subset of workspaces.',\n ],\n },\n rateLimit:\n 'The Admin API returns 429 with a Retry-After header on burst; the shared HTTP client honors it automatically. Daily syncs against the Usage and Cost reports are well below the per-organization Admin API budget.',\n limitations: [\n 'Only the organization Messages Usage Report and Cost Report endpoints are synced. Per-request logs and individual message bodies are not exposed by the Admin API.',\n 'All samples are bucketed daily (1d bucket_width). The Usage Report also supports hourly and per-minute granularity but those are not exposed here in v1.',\n 'The Cost Report only supports 1d bucket_width and reports cost in USD; non-USD billing currencies are not converted.',\n 'Admin API keys are required - regular sk-ant-api- keys do not have access to the organization Usage and Cost reports.',\n ],\n});\n\nconst PHASE_ORDER = ['usage_messages', 'cost_report'] as const;\n\ntype AnthropicPhase = (typeof PHASE_ORDER)[number];\n\nexport type AnthropicResource =\n | 'anthropic_input_tokens'\n | 'anthropic_output_tokens'\n | 'anthropic_cache_read_tokens'\n | 'anthropic_cache_creation_tokens'\n | 'anthropic_web_search_requests'\n | 'anthropic_cost_usd';\n\nconst isAnthropicSyncCursor = makeChunkedCursorGuard(PHASE_ORDER);\n\nconst RESOURCES_BY_PHASE: Record<AnthropicPhase, readonly AnthropicResource[]> =\n {\n usage_messages: [\n 'anthropic_input_tokens',\n 'anthropic_output_tokens',\n 'anthropic_cache_read_tokens',\n 'anthropic_cache_creation_tokens',\n 'anthropic_web_search_requests',\n ],\n cost_report: ['anthropic_cost_usd'],\n };\n\nconst PHASE_ENDPOINT_PATH: Record<AnthropicPhase, string> = {\n usage_messages: '/v1/organizations/usage_report/messages',\n cost_report: '/v1/organizations/cost_report',\n};\n\nconst usageCacheCreationSchema = z.object({\n ephemeral_1h_input_tokens: z.number().nonnegative().nullish(),\n ephemeral_5m_input_tokens: z.number().nonnegative().nullish(),\n});\n\nconst usageServerToolUseSchema = z.object({\n web_search_requests: z.number().int().nonnegative().nullish(),\n});\n\nconst usageResultSchema = z.object({\n account_id: z.string().nullish(),\n api_key_id: z.string().nullish(),\n cache_creation: usageCacheCreationSchema.nullish(),\n cache_read_input_tokens: z.number().nonnegative(),\n context_window: z.string().nullish(),\n inference_geo: z.string().nullish(),\n model: z.string().nullish(),\n output_tokens: z.number().nonnegative(),\n server_tool_use: usageServerToolUseSchema.nullish(),\n service_account_id: z.string().nullish(),\n service_tier: z.string().nullish(),\n uncached_input_tokens: z.number().nonnegative(),\n workspace_id: z.string().nullish(),\n});\n\nconst costResultSchema = z.object({\n amount: z.string(),\n context_window: z.string().nullish(),\n cost_type: z.string().nullish(),\n currency: z.string(),\n description: z.string().nullish(),\n inference_geo: z.string().nullish(),\n model: z.string().nullish(),\n service_tier: z.string().nullish(),\n token_type: z.string().nullish(),\n workspace_id: z.string().nullish(),\n});\n\nfunction bucketResponseSchema<T extends z.ZodTypeAny>(resultSchema: T) {\n return z.object({\n data: z.array(\n z.object({\n starting_at: z.string(),\n ending_at: z.string(),\n results: z.array(resultSchema),\n }),\n ),\n has_more: z.boolean(),\n next_page: z.string().nullish(),\n });\n}\n\nconst usageResponseSchema = bucketResponseSchema(usageResultSchema);\nconst costResponseSchema = bucketResponseSchema(costResultSchema);\n\ntype UsageResult = z.infer<typeof usageResultSchema>;\ntype CostResult = z.infer<typeof costResultSchema>;\n\ninterface BucketPage<TResult> {\n starting_at: string;\n ending_at: string;\n results: TResult[];\n}\n\ninterface PageResponse<TResult> {\n buckets: BucketPage<TResult>[];\n nextPage: string | null;\n}\n\nconst USAGE_DIMENSIONS = [\n {\n name: 'model',\n description: 'Claude model id reported by Anthropic (or null).',\n },\n {\n name: 'workspace_id',\n description:\n 'Anthropic workspace id the usage is attributed to (or null for the default workspace).',\n },\n {\n name: 'api_key_id',\n description: 'API key id the usage is attributed to (or null).',\n },\n {\n name: 'service_tier',\n description:\n 'Service tier the request ran under (standard, batch, priority, flex, etc.), or null.',\n },\n {\n name: 'context_window',\n description:\n 'Context window bucket the request used (0-200k or 200k-1M), or null.',\n },\n {\n name: 'inference_geo',\n description:\n 'Inference geo the request ran in (global, us, not_available), or null.',\n },\n] as const;\n\nconst COST_DIMENSIONS = [\n {\n name: 'workspace_id',\n description:\n 'Anthropic workspace id the cost is attributed to (or null for the default workspace).',\n },\n {\n name: 'description',\n description:\n 'Human-readable cost line item label (e.g. \"Claude Sonnet 4 Usage - Input Tokens\"), or null when ungrouped.',\n },\n {\n name: 'cost_type',\n description:\n 'Cost category (tokens, web_search, code_execution, session_usage), or null.',\n },\n {\n name: 'model',\n description:\n 'Claude model the cost is attributed to (or null for non-token costs).',\n },\n {\n name: 'token_type',\n description:\n 'Token category for token costs (uncached_input_tokens, output_tokens, cache_read_input_tokens, cache_creation.ephemeral_*_input_tokens), or null.',\n },\n {\n name: 'service_tier',\n description:\n 'Service tier the cost is attributed to (standard or batch), or null.',\n },\n {\n name: 'context_window',\n description:\n 'Context window the cost is attributed to (0-200k or 200k-1M), or null.',\n },\n {\n name: 'currency',\n description:\n 'Billing currency reported by Anthropic (currently always USD).',\n },\n] as const;\n\nexport const anthropicResources = defineResources({\n anthropic_input_tokens: {\n shape: 'metric',\n description:\n 'Daily uncached input tokens processed by the Anthropic Messages API, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Sample value is uncached_input_tokens. Cache-read and cache-creation token volumes are mirrored on their own metrics so a cache hit ratio can be computed at query time.',\n responses: { usage_messages: usageResponseSchema },\n },\n anthropic_output_tokens: {\n shape: 'metric',\n description:\n 'Daily output tokens generated by the Anthropic Messages API, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Written alongside anthropic_input_tokens from the same usage_messages API call.',\n },\n anthropic_cache_read_tokens: {\n shape: 'metric',\n description:\n 'Daily input tokens read from the prompt cache, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Cache hits are charged at a fraction of the uncached rate, so this metric paired with anthropic_input_tokens gives the cache hit ratio.',\n },\n anthropic_cache_creation_tokens: {\n shape: 'metric',\n description:\n 'Daily input tokens written into the prompt cache (sum of the 1h and 5m ephemeral caches), grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are mirrored in attributes for finer-grained widgets.',\n },\n anthropic_web_search_requests: {\n shape: 'metric',\n description:\n 'Daily count of web-search tool requests executed server-side by Claude, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'requests',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Sourced from server_tool_use.web_search_requests on each usage bucket. Zero rows are still written so a \"no usage today\" widget renders correctly.',\n },\n anthropic_cost_usd: {\n shape: 'metric',\n description:\n 'Daily organization spend in USD, broken down by workspace and cost line item, pulled from the Anthropic Cost Report.',\n endpoint: 'GET /v1/organizations/cost_report',\n unit: 'USD',\n granularity: 'daily',\n dimensions: [...COST_DIMENSIONS],\n notes:\n 'The Cost Report returns amounts as a decimal string in the lowest currency unit (cents for USD). The connector divides by 100 so the stored metric value is dollars. Costs can be revised for a couple of days after the fact; incremental syncs refetch a short trailing window to pick up adjustments.',\n responses: { cost_report: costResponseSchema },\n },\n});\n\nexport interface AnthropicSettings {\n workspaceIds?: readonly string[];\n resources?: readonly AnthropicResource[];\n lookbackDays?: number;\n}\n\nconst anthropicCredentials = {\n adminApiKey: {\n description: 'Anthropic organization admin API key (sk-ant-admin-...)',\n auth: 'required' as const,\n },\n} satisfies CredentialsSchema;\n\ntype AnthropicCredentials = typeof anthropicCredentials;\n\nexport const id = 'anthropic';\n\ninterface UsageWindow {\n startingAt: string;\n endingAt: string;\n}\n\nexport function getUsageWindow(\n options: SyncOptions,\n lookbackDays: number,\n now: number = Date.now(),\n): UsageWindow {\n const todayStart = Math.floor(now / MS_PER_DAY) * MS_PER_DAY;\n const endMs = todayStart + MS_PER_DAY;\n\n let days = lookbackDays;\n if (options.mode === 'latest') {\n days = INCREMENTAL_LOOKBACK_DAYS;\n } else if (options.since !== undefined) {\n const sinceMs = parseEpoch(options.since, 'iso');\n if (sinceMs !== null) {\n const elapsed = Math.ceil((now - sinceMs) / MS_PER_DAY);\n days = Math.min(\n Math.max(elapsed + INCREMENTAL_LOOKBACK_DAYS, 1),\n lookbackDays,\n );\n }\n }\n const startMs = endMs - days * MS_PER_DAY;\n return {\n startingAt: new Date(startMs).toISOString(),\n endingAt: new Date(endMs).toISOString(),\n };\n}\n\nfunction resourceToPhase(resource: AnthropicResource): AnthropicPhase {\n for (const phase of PHASE_ORDER) {\n if ((RESOURCES_BY_PHASE[phase] as readonly string[]).includes(resource)) {\n return phase;\n }\n }\n // unreachable - RESOURCES_BY_PHASE covers every AnthropicResource\n throw new Error(`anthropic: unmapped resource ${resource}`);\n}\n\nfunction nullableString(value: string | null | undefined): string | null {\n return value === undefined || value === null ? null : value;\n}\n\nfunction usageDimensionAttributes(row: UsageResult): Record<string, JSONValue> {\n return {\n model: nullableString(row.model),\n workspace_id: nullableString(row.workspace_id),\n api_key_id: nullableString(row.api_key_id),\n service_tier: nullableString(row.service_tier),\n context_window: nullableString(row.context_window),\n inference_geo: nullableString(row.inference_geo),\n account_id: nullableString(row.account_id),\n service_account_id: nullableString(row.service_account_id),\n };\n}\n\nfunction cacheCreationTotal(row: UsageResult): number {\n const c = row.cache_creation;\n if (!c) {\n return 0;\n }\n return (\n (c.ephemeral_1h_input_tokens ?? 0) + (c.ephemeral_5m_input_tokens ?? 0)\n );\n}\n\nfunction tsFromBucket(bucket: BucketPage<unknown>): number | null {\n return parseEpoch(bucket.starting_at, 'iso');\n}\n\nexport function buildUsageSamples(\n buckets: readonly BucketPage<UsageResult>[],\n): {\n inputTokens: MetricSample[];\n outputTokens: MetricSample[];\n cacheReadTokens: MetricSample[];\n cacheCreationTokens: MetricSample[];\n webSearchRequests: MetricSample[];\n} {\n const inputTokens: MetricSample[] = [];\n const outputTokens: MetricSample[] = [];\n const cacheReadTokens: MetricSample[] = [];\n const cacheCreationTokens: MetricSample[] = [];\n const webSearchRequests: MetricSample[] = [];\n for (const bucket of buckets) {\n const ts = tsFromBucket(bucket);\n if (ts === null) {\n continue;\n }\n for (const row of bucket.results) {\n const common = usageDimensionAttributes(row);\n const cacheCreation = row.cache_creation;\n inputTokens.push({\n name: 'anthropic_input_tokens',\n ts,\n value: row.uncached_input_tokens,\n attributes: { ...common },\n });\n outputTokens.push({\n name: 'anthropic_output_tokens',\n ts,\n value: row.output_tokens,\n attributes: { ...common },\n });\n cacheReadTokens.push({\n name: 'anthropic_cache_read_tokens',\n ts,\n value: row.cache_read_input_tokens,\n attributes: { ...common },\n });\n cacheCreationTokens.push({\n name: 'anthropic_cache_creation_tokens',\n ts,\n value: cacheCreationTotal(row),\n attributes: {\n ...common,\n ephemeral_1h_input_tokens:\n cacheCreation?.ephemeral_1h_input_tokens ?? 0,\n ephemeral_5m_input_tokens:\n cacheCreation?.ephemeral_5m_input_tokens ?? 0,\n },\n });\n webSearchRequests.push({\n name: 'anthropic_web_search_requests',\n ts,\n value: row.server_tool_use?.web_search_requests ?? 0,\n attributes: { ...common },\n });\n }\n }\n return {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n webSearchRequests,\n };\n}\n\nexport function buildCostSamples(\n buckets: readonly BucketPage<CostResult>[],\n): MetricSample[] {\n const samples: MetricSample[] = [];\n for (const bucket of buckets) {\n const ts = tsFromBucket(bucket);\n if (ts === null) {\n continue;\n }\n for (const row of bucket.results) {\n const rawAmount = Number.parseFloat(row.amount);\n const value = Number.isFinite(rawAmount)\n ? rawAmount / COST_AMOUNT_DIVISOR\n : 0;\n samples.push({\n name: 'anthropic_cost_usd',\n ts,\n value,\n attributes: {\n workspace_id: nullableString(row.workspace_id),\n description: nullableString(row.description),\n cost_type: nullableString(row.cost_type),\n model: nullableString(row.model),\n token_type: nullableString(row.token_type),\n service_tier: nullableString(row.service_tier),\n context_window: nullableString(row.context_window),\n currency: row.currency,\n },\n });\n }\n }\n return samples;\n}\n\nexport class AnthropicConnector extends BaseConnector<\n AnthropicSettings,\n AnthropicCredentials\n> {\n static readonly id = id;\n\n static readonly resources = anthropicResources;\n\n static readonly schemas = schemasFromResources(anthropicResources);\n\n static create(input: unknown, ctx?: ConnectorContext): AnthropicConnector {\n const parsed = configFields.parse(input);\n return new AnthropicConnector(\n {\n workspaceIds: parsed.workspaceIds,\n resources: parsed.resources,\n lookbackDays: parsed.lookbackDays,\n },\n { adminApiKey: parsed.adminApiKey },\n ctx,\n );\n }\n\n readonly id = id;\n override readonly credentials = anthropicCredentials;\n\n private buildHeaders(): Record<string, string> {\n return {\n 'X-Api-Key': String(this.creds.adminApiKey),\n 'anthropic-version': ANTHROPIC_API_VERSION,\n 'User-Agent': connectorUserAgent(this.id),\n };\n }\n\n private fetch<T>(\n url: string,\n resource: string,\n signal?: AbortSignal,\n ): Promise<HttpResponse<T>> {\n return this.get<T>(url, {\n resource,\n headers: this.buildHeaders(),\n signal,\n });\n }\n\n private buildInitialUrl(phase: AnthropicPhase, window: UsageWindow): string {\n const url = new URL(`${ANTHROPIC_API_BASE}${PHASE_ENDPOINT_PATH[phase]}`);\n url.searchParams.set('starting_at', window.startingAt);\n url.searchParams.set('ending_at', window.endingAt);\n url.searchParams.set('bucket_width', '1d');\n if (phase === 'usage_messages') {\n url.searchParams.set('limit', String(USAGE_PAGE_LIMIT));\n url.searchParams.append('group_by', 'model');\n url.searchParams.append('group_by', 'workspace_id');\n url.searchParams.append('group_by', 'api_key_id');\n url.searchParams.append('group_by', 'service_tier');\n url.searchParams.append('group_by', 'context_window');\n url.searchParams.append('group_by', 'inference_geo');\n for (const workspaceId of this.settings.workspaceIds ?? []) {\n url.searchParams.append('workspace_ids', workspaceId);\n }\n } else {\n url.searchParams.set('limit', String(COSTS_PAGE_LIMIT));\n url.searchParams.append('group_by', 'workspace_id');\n url.searchParams.append('group_by', 'description');\n }\n return url.toString();\n }\n\n private buildNextUrl(currentUrl: string, nextPage: string): string {\n const url = new URL(currentUrl);\n url.searchParams.set('page', nextPage);\n return url.toString();\n }\n\n private async fetchPhasePage<T>(\n phase: AnthropicPhase,\n schema: z.ZodType<T>,\n initialUrl: string,\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<{ url: string; parsed: T; nextUrl: string | null }> {\n const url = page ?? initialUrl;\n const res = await this.fetch<unknown>(url, phase, signal);\n const parsed = schema.parse(res.body);\n const body = parsed as unknown as {\n next_page?: string | null;\n has_more?: boolean;\n };\n const nextPage =\n body.has_more === true &&\n typeof body.next_page === 'string' &&\n body.next_page.length > 0\n ? body.next_page\n : null;\n const nextUrl = nextPage ? this.buildNextUrl(url, nextPage) : null;\n return { url, parsed, nextUrl };\n }\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n const cursor = isAnthropicSyncCursor(options.cursor)\n ? options.cursor\n : undefined;\n const lookbackDays = this.settings.lookbackDays ?? DEFAULT_LOOKBACK_DAYS;\n const window = getUsageWindow(options, lookbackDays);\n\n const phases = selectActivePhases<AnthropicResource, AnthropicPhase>(\n resourceToPhase,\n PHASE_ORDER,\n this.settings.resources,\n );\n\n const startIdx = cursor ? phases.indexOf(cursor.phase) : 0;\n const resumeIdx = startIdx >= 0 ? startIdx : 0;\n\n for (let i = resumeIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n if (signal?.aborted) {\n return { done: false, cursor: { phase, page: null } };\n }\n const phaseStart = Date.now();\n const initialUrl = this.buildInitialUrl(phase, window);\n let pageUrl: string | null = null;\n let pageCount = 0;\n const buckets: BucketPage<unknown>[] = [];\n\n while (true) {\n if (signal?.aborted) {\n return { done: false, cursor: { phase, page: null } };\n }\n pageCount += 1;\n const { parsed, nextUrl } = await this.fetchAnyPhasePage(\n phase,\n initialUrl,\n pageUrl,\n signal,\n );\n const data = parsed.data as BucketPage<unknown>[];\n buckets.push(...data);\n this.logger.info('fetched page', {\n resource: phase,\n page: pageCount,\n items: data.length,\n });\n if (nextUrl === null) {\n break;\n }\n pageUrl = nextUrl;\n }\n\n await this.writePhase(storage, phase, buckets);\n this.logger.info('resource done', {\n resource: phase,\n pages: pageCount,\n items: buckets.length,\n duration_ms: Date.now() - phaseStart,\n });\n }\n\n return { done: true };\n }\n\n private async fetchAnyPhasePage(\n phase: AnthropicPhase,\n initialUrl: string,\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<{\n parsed: { data: BucketPage<unknown>[] };\n nextUrl: string | null;\n }> {\n switch (phase) {\n case 'usage_messages':\n return this.fetchPhasePage(\n phase,\n usageResponseSchema,\n initialUrl,\n page,\n signal,\n );\n case 'cost_report':\n return this.fetchPhasePage(\n phase,\n costResponseSchema,\n initialUrl,\n page,\n signal,\n );\n }\n }\n\n private async writePhase(\n storage: StorageHandle,\n phase: AnthropicPhase,\n buckets: BucketPage<unknown>[],\n ): Promise<void> {\n switch (phase) {\n case 'usage_messages': {\n const samples = buildUsageSamples(buckets as BucketPage<UsageResult>[]);\n await storage.metrics(samples.inputTokens, {\n names: ['anthropic_input_tokens'],\n });\n await storage.metrics(samples.outputTokens, {\n names: ['anthropic_output_tokens'],\n });\n await storage.metrics(samples.cacheReadTokens, {\n names: ['anthropic_cache_read_tokens'],\n });\n await storage.metrics(samples.cacheCreationTokens, {\n names: ['anthropic_cache_creation_tokens'],\n });\n await storage.metrics(samples.webSearchRequests, {\n names: ['anthropic_web_search_requests'],\n });\n return;\n }\n case 'cost_report': {\n const samples = buildCostSamples(buckets as BucketPage<CostResult>[]);\n await storage.metrics(samples, { names: ['anthropic_cost_usd'] });\n return;\n }\n }\n }\n}\n\nexport type { PageResponse, BucketPage, UsageResult, CostResult };\n","import { AnthropicConnector } from './anthropic';\n\nexport {\n AnthropicConnector,\n anthropicResources as resources,\n buildCostSamples,\n buildUsageSamples,\n configFields,\n doc,\n getUsageWindow,\n id,\n} from './anthropic';\nexport type {\n AnthropicResource,\n AnthropicSettings,\n BucketPage,\n CostResult,\n PageResponse,\n UsageResult,\n} from './anthropic';\nexport default AnthropicConnector;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../connector-shared/src/errors.ts","../../../connector-shared/src/retry.ts","../../../connector-shared/src/version.ts","../../../connector-shared/src/request.ts","../../../connector-shared/src/rate-limit.ts","../../../connector-shared/src/map-concurrent.ts","../../../connector-shared/src/sanitize.ts","../../../connector-shared/src/epoch.ts","../../../connector-shared/src/pagination.ts","../../../connector-shared/src/logger.ts","../src/anthropic.ts","../src/index.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n\nexport function connectorUserAgent(connectorId: string): string {\n return `rawdash-connector-${connectorId}/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n}\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport interface StandardRateLimitPolicyConfig {\n remainingHeader: string;\n resetHeader: string;\n resetUnit: 's' | 'ms';\n resetFallbackMs?: number;\n}\n\nexport function standardRateLimitPolicy(\n config: StandardRateLimitPolicyConfig,\n): RateLimitPolicy {\n const { remainingHeader, resetHeader, resetUnit, resetFallbackMs } = config;\n const multiplier = resetUnit === 's' ? 1000 : 1;\n return {\n parse(h) {\n const remainingRaw = h.get(remainingHeader);\n if (remainingRaw === null || remainingRaw.trim() === '') {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n const resetRaw = h.get(resetHeader);\n if (resetRaw === null) {\n if (resetFallbackMs === undefined) {\n return null;\n }\n return {\n remaining,\n resetAt: new Date(Date.now() + resetFallbackMs),\n };\n }\n if (resetRaw.trim() === '') {\n return null;\n }\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n const resetMs = reset * multiplier;\n if (!Number.isFinite(resetMs)) {\n return null;\n }\n return { remaining, resetAt: new Date(resetMs) };\n },\n };\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n if (items.length === 0) {\n return results;\n }\n const normalized = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const limit = Math.max(1, Math.min(normalized, items.length));\n let next = 0;\n let failed = false;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const i = next++;\n if (i >= items.length) {\n return;\n }\n try {\n results[i] = await fn(items[i]!, i);\n } catch (err) {\n failed = true;\n throw err;\n }\n }\n }\n\n const workers: Promise<void>[] = [];\n for (let w = 0; w < limit; w++) {\n workers.push(worker());\n }\n await Promise.all(workers);\n return results;\n}\n","export interface SanitizeAllowedUrlOptions {\n url: string | null;\n host: string;\n pathname: string;\n protocol?: 'https:' | 'http:';\n}\n\nexport function sanitizeAllowedUrl(\n options: SanitizeAllowedUrlOptions,\n): string | null {\n const { url, host, pathname, protocol = 'https:' } = options;\n if (url === null) {\n return null;\n }\n try {\n const u = new URL(url);\n if (u.protocol !== protocol || u.host !== host || u.pathname !== pathname) {\n return null;\n }\n return u.toString();\n } catch {\n return null;\n }\n}\n","export type EpochUnit = 'ms' | 's' | 'iso';\n\nexport function parseEpoch(\n value: number | string | null | undefined,\n unit: EpochUnit,\n): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (unit === 'iso') {\n if (typeof value !== 'string') {\n return null;\n }\n const ms = new Date(value).getTime();\n return Number.isFinite(ms) ? ms : null;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return null;\n }\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return null;\n }\n const result = unit === 's' ? n * 1000 : n;\n return Number.isFinite(result) ? result : null;\n}\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type LogFields = Record<string, unknown>;\n\nexport interface ConnectorLogger {\n info(event: string, fields?: LogFields): void;\n warn(event: string, fields?: LogFields): void;\n}\n\nexport interface ConnectorLoggerOptions {\n scope: string;\n}\n\nconst MAX_VALUE_LEN = 120;\n\nfunction truncate(s: string, max = MAX_VALUE_LEN): string {\n if (s.length <= max) {\n return s;\n }\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return '';\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'string') {\n const t = truncate(value);\n if (/[\\s\"=]/.test(t)) {\n return JSON.stringify(t);\n }\n return t;\n }\n if (typeof value === 'bigint') {\n return value.toString();\n }\n let json: string | undefined;\n try {\n json = JSON.stringify(value);\n } catch {\n json = undefined;\n }\n return truncate(json ?? String(value));\n}\n\nexport function formatLogFields(fields?: LogFields): string {\n if (!fields) {\n return '';\n }\n const parts: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v === undefined) {\n continue;\n }\n parts.push(`${k}=${formatValue(v)}`);\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nexport function formatLogLine(\n scope: string,\n event: string,\n fields?: LogFields,\n): string {\n return `[${scope}] ${event}${formatLogFields(fields)}`;\n}\n\nexport function createDefaultConnectorLogger(\n opts: ConnectorLoggerOptions,\n): ConnectorLogger {\n return {\n info(event, fields) {\n console.info(formatLogLine(opts.scope, event, fields));\n },\n warn(event, fields) {\n console.warn(formatLogLine(opts.scope, event, fields));\n },\n };\n}\n\nconst NOOP_LOGGER: ConnectorLogger = {\n info() {},\n warn() {},\n};\n\nexport function noopConnectorLogger(): ConnectorLogger {\n return NOOP_LOGGER;\n}\n","import {\n type HttpResponse,\n connectorUserAgent,\n parseEpoch,\n} from '@rawdash/connector-shared';\nimport {\n BaseConnector,\n type ConnectorContext,\n type ConnectorDoc,\n type CredentialsSchema,\n type MetricSample,\n type StorageHandle,\n type SyncOptions,\n type SyncResult,\n defineConfigFields,\n defineConnectorDoc,\n defineResources,\n makeChunkedCursorGuard,\n metricSample,\n schemasFromResources,\n selectActivePhases,\n} from '@rawdash/core';\nimport { z } from 'zod';\n\nconst ANTHROPIC_API_HOST = 'api.anthropic.com';\nconst ANTHROPIC_API_BASE = `https://${ANTHROPIC_API_HOST}`;\nconst ANTHROPIC_API_VERSION = '2023-06-01';\nconst USAGE_PAGE_LIMIT = 31;\nconst COSTS_PAGE_LIMIT = 31;\nconst MS_PER_DAY = 86_400_000;\nconst DEFAULT_LOOKBACK_DAYS = 30;\nconst INCREMENTAL_LOOKBACK_DAYS = 2;\n// Cost report `amount` is a decimal string in the lowest currency unit (cents\n// for USD): e.g. \"123.45\" represents $1.2345. Divide by 100 to get dollars.\nconst COST_AMOUNT_DIVISOR = 100;\n\nexport const configFields = defineConfigFields(\n z.object({\n adminApiKey: z.object({ $secret: z.string().min(1) }).meta({\n label: 'Admin API key',\n description:\n 'Anthropic organization admin API key (starts with sk-ant-admin-). Create one at console.anthropic.com -> Settings -> Admin keys. Regular API keys (sk-ant-api-) cannot read the Usage and Cost reports.',\n placeholder: 'ANTHROPIC_ADMIN_API_KEY',\n secret: true,\n }),\n workspaceIds: z.array(z.string().min(1)).nonempty().optional().meta({\n label: 'Workspace IDs (optional)',\n description:\n 'Restrict usage and cost queries to specific Anthropic workspace ids (wrkspc_...). Omit to aggregate every workspace the admin key can see.',\n }),\n resources: z\n .array(\n z.enum([\n 'anthropic_input_tokens',\n 'anthropic_output_tokens',\n 'anthropic_cache_read_tokens',\n 'anthropic_cache_creation_tokens',\n 'anthropic_web_search_requests',\n 'anthropic_cost_usd',\n ]),\n )\n .nonempty()\n .optional()\n .meta({\n label: 'Resources',\n description:\n 'Which Anthropic metric series to sync. Omit to sync all of them. The five usage metrics share one upstream call to the Messages Usage Report; enabling any one of them fetches the report and writes all five.',\n }),\n lookbackDays: z.number().int().positive().max(180).optional().meta({\n label: 'Backfill window (days)',\n description:\n 'How many days of usage history to fetch on a full sync. Defaults to 30. The Usage Report returns at most 31 buckets per page, so longer windows paginate.',\n placeholder: '30',\n }),\n }),\n);\n\nexport const doc: ConnectorDoc = defineConnectorDoc({\n displayName: 'Anthropic',\n category: 'engineering',\n brandColor: '#D97757',\n tagline:\n 'Track Anthropic spend, daily token usage across Claude models, cache hit volumes, and web-search tool requests from the Anthropic Admin API.',\n vendor: {\n name: 'Anthropic',\n domain: 'anthropic.com',\n apiDocs:\n 'https://docs.claude.com/en/api/admin-api/usage-cost/get-messages-usage-report',\n website: 'https://anthropic.com',\n },\n auth: {\n summary:\n 'Authenticates with an Anthropic organization admin API key (sk-ant-admin-). Admin keys are the only key class that can read the Usage and Cost reports; regular API keys return 403.',\n setup: [\n 'Open console.anthropic.com -> Settings -> Admin Keys and create a new admin key. Admin keys are organization-scoped, so create the key from the organization whose usage you want to read.',\n 'Store the key as a secret (e.g. ANTHROPIC_ADMIN_API_KEY).',\n 'Reference it from config as `adminApiKey: secret(\"ANTHROPIC_ADMIN_API_KEY\")`.',\n 'Optionally set `workspaceIds` to restrict the query to a subset of workspaces.',\n ],\n },\n rateLimit:\n 'The Admin API returns 429 with a Retry-After header on burst; the shared HTTP client honors it automatically. Daily syncs against the Usage and Cost reports are well below the per-organization Admin API budget.',\n limitations: [\n 'Only the organization Messages Usage Report and Cost Report endpoints are synced. Per-request logs and individual message bodies are not exposed by the Admin API.',\n 'All samples are bucketed daily (1d bucket_width). The Usage Report also supports hourly and per-minute granularity but those are not exposed here in v1.',\n 'The Cost Report only supports 1d bucket_width and reports cost in USD; non-USD billing currencies are not converted.',\n 'Admin API keys are required - regular sk-ant-api- keys do not have access to the organization Usage and Cost reports.',\n ],\n});\n\nconst PHASE_ORDER = ['usage_messages', 'cost_report'] as const;\n\ntype AnthropicPhase = (typeof PHASE_ORDER)[number];\n\nexport type AnthropicResource =\n | 'anthropic_input_tokens'\n | 'anthropic_output_tokens'\n | 'anthropic_cache_read_tokens'\n | 'anthropic_cache_creation_tokens'\n | 'anthropic_web_search_requests'\n | 'anthropic_cost_usd';\n\nconst isAnthropicSyncCursor = makeChunkedCursorGuard(PHASE_ORDER);\n\nconst RESOURCES_BY_PHASE: Record<AnthropicPhase, readonly AnthropicResource[]> =\n {\n usage_messages: [\n 'anthropic_input_tokens',\n 'anthropic_output_tokens',\n 'anthropic_cache_read_tokens',\n 'anthropic_cache_creation_tokens',\n 'anthropic_web_search_requests',\n ],\n cost_report: ['anthropic_cost_usd'],\n };\n\nconst PHASE_ENDPOINT_PATH: Record<AnthropicPhase, string> = {\n usage_messages: '/v1/organizations/usage_report/messages',\n cost_report: '/v1/organizations/cost_report',\n};\n\nconst usageCacheCreationSchema = z.object({\n ephemeral_1h_input_tokens: z.number().nonnegative().nullish(),\n ephemeral_5m_input_tokens: z.number().nonnegative().nullish(),\n});\n\nconst usageServerToolUseSchema = z.object({\n web_search_requests: z.number().int().nonnegative().nullish(),\n});\n\nconst usageResultSchema = z.object({\n account_id: z.string().nullish(),\n api_key_id: z.string().nullish(),\n cache_creation: usageCacheCreationSchema.nullish(),\n cache_read_input_tokens: z.number().nonnegative(),\n context_window: z.string().nullish(),\n inference_geo: z.string().nullish(),\n model: z.string().nullish(),\n output_tokens: z.number().nonnegative(),\n server_tool_use: usageServerToolUseSchema.nullish(),\n service_account_id: z.string().nullish(),\n service_tier: z.string().nullish(),\n uncached_input_tokens: z.number().nonnegative(),\n workspace_id: z.string().nullish(),\n});\n\nconst costResultSchema = z.object({\n amount: z.string(),\n context_window: z.string().nullish(),\n cost_type: z.string().nullish(),\n currency: z.string(),\n description: z.string().nullish(),\n inference_geo: z.string().nullish(),\n model: z.string().nullish(),\n service_tier: z.string().nullish(),\n token_type: z.string().nullish(),\n workspace_id: z.string().nullish(),\n});\n\nfunction bucketResponseSchema<T extends z.ZodTypeAny>(resultSchema: T) {\n return z.object({\n data: z.array(\n z.object({\n starting_at: z.string(),\n ending_at: z.string(),\n results: z.array(resultSchema),\n }),\n ),\n has_more: z.boolean(),\n next_page: z.string().nullish(),\n });\n}\n\nconst usageResponseSchema = bucketResponseSchema(usageResultSchema);\nconst costResponseSchema = bucketResponseSchema(costResultSchema);\n\ntype UsageResult = z.infer<typeof usageResultSchema>;\ntype CostResult = z.infer<typeof costResultSchema>;\n\ninterface BucketPage<TResult> {\n starting_at: string;\n ending_at: string;\n results: TResult[];\n}\n\ninterface PageResponse<TResult> {\n buckets: BucketPage<TResult>[];\n nextPage: string | null;\n}\n\nconst USAGE_DIMENSIONS = [\n {\n name: 'model',\n description: 'Claude model id reported by Anthropic (or null).',\n },\n {\n name: 'workspace_id',\n description:\n 'Anthropic workspace id the usage is attributed to (or null for the default workspace).',\n },\n {\n name: 'api_key_id',\n description: 'API key id the usage is attributed to (or null).',\n },\n {\n name: 'service_tier',\n description:\n 'Service tier the request ran under (standard, batch, priority, flex, etc.), or null.',\n },\n {\n name: 'context_window',\n description:\n 'Context window bucket the request used (0-200k or 200k-1M), or null.',\n },\n {\n name: 'inference_geo',\n description:\n 'Inference geo the request ran in (global, us, not_available), or null.',\n },\n {\n name: 'account_id',\n description: 'Account id the usage is attributed to (or null).',\n },\n {\n name: 'service_account_id',\n description: 'Service account id the usage is attributed to (or null).',\n },\n] as const;\n\nconst COST_DIMENSIONS = [\n {\n name: 'workspace_id',\n description:\n 'Anthropic workspace id the cost is attributed to (or null for the default workspace).',\n },\n {\n name: 'description',\n description:\n 'Human-readable cost line item label (e.g. \"Claude Sonnet 4 Usage - Input Tokens\"), or null when ungrouped.',\n },\n {\n name: 'cost_type',\n description:\n 'Cost category (tokens, web_search, code_execution, session_usage), or null.',\n },\n {\n name: 'model',\n description:\n 'Claude model the cost is attributed to (or null for non-token costs).',\n },\n {\n name: 'token_type',\n description:\n 'Token category for token costs (uncached_input_tokens, output_tokens, cache_read_input_tokens, cache_creation.ephemeral_*_input_tokens), or null.',\n },\n {\n name: 'service_tier',\n description:\n 'Service tier the cost is attributed to (standard or batch), or null.',\n },\n {\n name: 'context_window',\n description:\n 'Context window the cost is attributed to (0-200k or 200k-1M), or null.',\n },\n {\n name: 'currency',\n description:\n 'Billing currency reported by Anthropic (currently always USD).',\n },\n] as const;\n\nexport const anthropicResources = defineResources({\n anthropic_input_tokens: {\n shape: 'metric',\n description:\n 'Daily uncached input tokens processed by the Anthropic Messages API, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Sample value is uncached_input_tokens. Cache-read and cache-creation token volumes are mirrored on their own metrics so a cache hit ratio can be computed at query time.',\n responses: { usage_messages: usageResponseSchema },\n },\n anthropic_output_tokens: {\n shape: 'metric',\n description:\n 'Daily output tokens generated by the Anthropic Messages API, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Written alongside anthropic_input_tokens from the same usage_messages API call.',\n },\n anthropic_cache_read_tokens: {\n shape: 'metric',\n description:\n 'Daily input tokens read from the prompt cache, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Cache hits are charged at a fraction of the uncached rate, so this metric paired with anthropic_input_tokens gives the cache hit ratio.',\n },\n anthropic_cache_creation_tokens: {\n shape: 'metric',\n description:\n 'Daily input tokens written into the prompt cache (sum of the 1h and 5m ephemeral caches), grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'tokens',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n measures: [\n {\n name: 'ephemeral_1h_input_tokens',\n description:\n 'Input tokens written into the 1-hour ephemeral prompt cache (a component of the sample value).',\n },\n {\n name: 'ephemeral_5m_input_tokens',\n description:\n 'Input tokens written into the 5-minute ephemeral prompt cache (a component of the sample value).',\n },\n ],\n notes:\n 'The per-cache-bucket counts (ephemeral_1h_input_tokens, ephemeral_5m_input_tokens) are declared measures for finer-grained widgets.',\n },\n anthropic_web_search_requests: {\n shape: 'metric',\n description:\n 'Daily count of web-search tool requests executed server-side by Claude, grouped by model and workspace.',\n endpoint: 'GET /v1/organizations/usage_report/messages',\n unit: 'requests',\n granularity: 'daily',\n dimensions: [...USAGE_DIMENSIONS],\n notes:\n 'Sourced from server_tool_use.web_search_requests on each usage bucket. Zero rows are still written so a \"no usage today\" widget renders correctly.',\n },\n anthropic_cost_usd: {\n shape: 'metric',\n description:\n 'Daily organization spend in USD, broken down by workspace and cost line item, pulled from the Anthropic Cost Report.',\n endpoint: 'GET /v1/organizations/cost_report',\n unit: 'USD',\n granularity: 'daily',\n dimensions: [...COST_DIMENSIONS],\n notes:\n 'The Cost Report returns amounts as a decimal string in the lowest currency unit (cents for USD). The connector divides by 100 so the stored metric value is dollars. Costs can be revised for a couple of days after the fact; incremental syncs refetch a short trailing window to pick up adjustments.',\n responses: { cost_report: costResponseSchema },\n },\n});\n\nexport interface AnthropicSettings {\n workspaceIds?: readonly string[];\n resources?: readonly AnthropicResource[];\n lookbackDays?: number;\n}\n\nconst anthropicCredentials = {\n adminApiKey: {\n description: 'Anthropic organization admin API key (sk-ant-admin-...)',\n auth: 'required' as const,\n },\n} satisfies CredentialsSchema;\n\ntype AnthropicCredentials = typeof anthropicCredentials;\n\nexport const id = 'anthropic';\n\ninterface UsageWindow {\n startingAt: string;\n endingAt: string;\n}\n\nexport function getUsageWindow(\n options: SyncOptions,\n lookbackDays: number,\n now: number = Date.now(),\n): UsageWindow {\n const todayStart = Math.floor(now / MS_PER_DAY) * MS_PER_DAY;\n const endMs = todayStart + MS_PER_DAY;\n\n let days = lookbackDays;\n if (options.mode === 'latest') {\n days = INCREMENTAL_LOOKBACK_DAYS;\n } else if (options.since !== undefined) {\n const sinceMs = parseEpoch(options.since, 'iso');\n if (sinceMs !== null) {\n const elapsed = Math.ceil((now - sinceMs) / MS_PER_DAY);\n days = Math.min(\n Math.max(elapsed + INCREMENTAL_LOOKBACK_DAYS, 1),\n lookbackDays,\n );\n }\n }\n const startMs = endMs - days * MS_PER_DAY;\n return {\n startingAt: new Date(startMs).toISOString(),\n endingAt: new Date(endMs).toISOString(),\n };\n}\n\nfunction resourceToPhase(resource: AnthropicResource): AnthropicPhase {\n for (const phase of PHASE_ORDER) {\n if ((RESOURCES_BY_PHASE[phase] as readonly string[]).includes(resource)) {\n return phase;\n }\n }\n // unreachable - RESOURCES_BY_PHASE covers every AnthropicResource\n throw new Error(`anthropic: unmapped resource ${resource}`);\n}\n\nfunction nullableString(value: string | null | undefined): string | null {\n return value === undefined || value === null ? null : value;\n}\n\ninterface UsageDimensionAttributes {\n model: string | null;\n workspace_id: string | null;\n api_key_id: string | null;\n service_tier: string | null;\n context_window: string | null;\n inference_geo: string | null;\n account_id: string | null;\n service_account_id: string | null;\n}\n\nfunction usageDimensionAttributes(row: UsageResult): UsageDimensionAttributes {\n return {\n model: nullableString(row.model),\n workspace_id: nullableString(row.workspace_id),\n api_key_id: nullableString(row.api_key_id),\n service_tier: nullableString(row.service_tier),\n context_window: nullableString(row.context_window),\n inference_geo: nullableString(row.inference_geo),\n account_id: nullableString(row.account_id),\n service_account_id: nullableString(row.service_account_id),\n };\n}\n\nfunction cacheCreationTotal(row: UsageResult): number {\n const c = row.cache_creation;\n if (!c) {\n return 0;\n }\n return (\n (c.ephemeral_1h_input_tokens ?? 0) + (c.ephemeral_5m_input_tokens ?? 0)\n );\n}\n\nfunction tsFromBucket(bucket: BucketPage<unknown>): number | null {\n return parseEpoch(bucket.starting_at, 'iso');\n}\n\nexport function buildUsageSamples(\n buckets: readonly BucketPage<UsageResult>[],\n): {\n inputTokens: MetricSample[];\n outputTokens: MetricSample[];\n cacheReadTokens: MetricSample[];\n cacheCreationTokens: MetricSample[];\n webSearchRequests: MetricSample[];\n} {\n const inputTokens: MetricSample[] = [];\n const outputTokens: MetricSample[] = [];\n const cacheReadTokens: MetricSample[] = [];\n const cacheCreationTokens: MetricSample[] = [];\n const webSearchRequests: MetricSample[] = [];\n for (const bucket of buckets) {\n const ts = tsFromBucket(bucket);\n if (ts === null) {\n continue;\n }\n for (const row of bucket.results) {\n const common = usageDimensionAttributes(row);\n const cacheCreation = row.cache_creation;\n inputTokens.push(\n metricSample(anthropicResources, 'anthropic_input_tokens', {\n ts,\n value: row.uncached_input_tokens,\n attributes: { ...common },\n }),\n );\n outputTokens.push(\n metricSample(anthropicResources, 'anthropic_output_tokens', {\n ts,\n value: row.output_tokens,\n attributes: { ...common },\n }),\n );\n cacheReadTokens.push(\n metricSample(anthropicResources, 'anthropic_cache_read_tokens', {\n ts,\n value: row.cache_read_input_tokens,\n attributes: { ...common },\n }),\n );\n cacheCreationTokens.push(\n metricSample(anthropicResources, 'anthropic_cache_creation_tokens', {\n ts,\n value: cacheCreationTotal(row),\n attributes: {\n ...common,\n ephemeral_1h_input_tokens:\n cacheCreation?.ephemeral_1h_input_tokens ?? 0,\n ephemeral_5m_input_tokens:\n cacheCreation?.ephemeral_5m_input_tokens ?? 0,\n },\n }),\n );\n webSearchRequests.push(\n metricSample(anthropicResources, 'anthropic_web_search_requests', {\n ts,\n value: row.server_tool_use?.web_search_requests ?? 0,\n attributes: { ...common },\n }),\n );\n }\n }\n return {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n webSearchRequests,\n };\n}\n\nexport function buildCostSamples(\n buckets: readonly BucketPage<CostResult>[],\n): MetricSample[] {\n const samples: MetricSample[] = [];\n for (const bucket of buckets) {\n const ts = tsFromBucket(bucket);\n if (ts === null) {\n continue;\n }\n for (const row of bucket.results) {\n const rawAmount = Number.parseFloat(row.amount);\n const value = Number.isFinite(rawAmount)\n ? rawAmount / COST_AMOUNT_DIVISOR\n : 0;\n samples.push(\n metricSample(anthropicResources, 'anthropic_cost_usd', {\n ts,\n value,\n attributes: {\n workspace_id: nullableString(row.workspace_id),\n description: nullableString(row.description),\n cost_type: nullableString(row.cost_type),\n model: nullableString(row.model),\n token_type: nullableString(row.token_type),\n service_tier: nullableString(row.service_tier),\n context_window: nullableString(row.context_window),\n currency: row.currency,\n },\n }),\n );\n }\n }\n return samples;\n}\n\nexport class AnthropicConnector extends BaseConnector<\n AnthropicSettings,\n AnthropicCredentials\n> {\n static readonly id = id;\n\n static readonly resources = anthropicResources;\n\n static readonly schemas = schemasFromResources(anthropicResources);\n\n static create(input: unknown, ctx?: ConnectorContext): AnthropicConnector {\n const parsed = configFields.parse(input);\n return new AnthropicConnector(\n {\n workspaceIds: parsed.workspaceIds,\n resources: parsed.resources,\n lookbackDays: parsed.lookbackDays,\n },\n { adminApiKey: parsed.adminApiKey },\n ctx,\n );\n }\n\n readonly id = id;\n override readonly credentials = anthropicCredentials;\n\n private buildHeaders(): Record<string, string> {\n return {\n 'X-Api-Key': String(this.creds.adminApiKey),\n 'anthropic-version': ANTHROPIC_API_VERSION,\n 'User-Agent': connectorUserAgent(this.id),\n };\n }\n\n private fetch<T>(\n url: string,\n resource: string,\n signal?: AbortSignal,\n ): Promise<HttpResponse<T>> {\n return this.get<T>(url, {\n resource,\n headers: this.buildHeaders(),\n signal,\n });\n }\n\n private buildInitialUrl(phase: AnthropicPhase, window: UsageWindow): string {\n const url = new URL(`${ANTHROPIC_API_BASE}${PHASE_ENDPOINT_PATH[phase]}`);\n url.searchParams.set('starting_at', window.startingAt);\n url.searchParams.set('ending_at', window.endingAt);\n url.searchParams.set('bucket_width', '1d');\n if (phase === 'usage_messages') {\n url.searchParams.set('limit', String(USAGE_PAGE_LIMIT));\n url.searchParams.append('group_by', 'model');\n url.searchParams.append('group_by', 'workspace_id');\n url.searchParams.append('group_by', 'api_key_id');\n url.searchParams.append('group_by', 'service_tier');\n url.searchParams.append('group_by', 'context_window');\n url.searchParams.append('group_by', 'inference_geo');\n for (const workspaceId of this.settings.workspaceIds ?? []) {\n url.searchParams.append('workspace_ids', workspaceId);\n }\n } else {\n url.searchParams.set('limit', String(COSTS_PAGE_LIMIT));\n url.searchParams.append('group_by', 'workspace_id');\n url.searchParams.append('group_by', 'description');\n }\n return url.toString();\n }\n\n private buildNextUrl(currentUrl: string, nextPage: string): string {\n const url = new URL(currentUrl);\n url.searchParams.set('page', nextPage);\n return url.toString();\n }\n\n private async fetchPhasePage<T>(\n phase: AnthropicPhase,\n schema: z.ZodType<T>,\n initialUrl: string,\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<{ url: string; parsed: T; nextUrl: string | null }> {\n const url = page ?? initialUrl;\n const res = await this.fetch<unknown>(url, phase, signal);\n const parsed = schema.parse(res.body);\n const body = parsed as unknown as {\n next_page?: string | null;\n has_more?: boolean;\n };\n const nextPage =\n body.has_more === true &&\n typeof body.next_page === 'string' &&\n body.next_page.length > 0\n ? body.next_page\n : null;\n const nextUrl = nextPage ? this.buildNextUrl(url, nextPage) : null;\n return { url, parsed, nextUrl };\n }\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n const cursor = isAnthropicSyncCursor(options.cursor)\n ? options.cursor\n : undefined;\n const lookbackDays = this.settings.lookbackDays ?? DEFAULT_LOOKBACK_DAYS;\n const window = getUsageWindow(options, lookbackDays);\n\n const phases = selectActivePhases<AnthropicResource, AnthropicPhase>(\n resourceToPhase,\n PHASE_ORDER,\n this.settings.resources,\n );\n\n const startIdx = cursor ? phases.indexOf(cursor.phase) : 0;\n const resumeIdx = startIdx >= 0 ? startIdx : 0;\n\n for (let i = resumeIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n if (signal?.aborted) {\n return { done: false, cursor: { phase, page: null } };\n }\n const phaseStart = Date.now();\n const initialUrl = this.buildInitialUrl(phase, window);\n let pageUrl: string | null = null;\n let pageCount = 0;\n const buckets: BucketPage<unknown>[] = [];\n\n while (true) {\n if (signal?.aborted) {\n return { done: false, cursor: { phase, page: null } };\n }\n pageCount += 1;\n const { parsed, nextUrl } = await this.fetchAnyPhasePage(\n phase,\n initialUrl,\n pageUrl,\n signal,\n );\n const data = parsed.data as BucketPage<unknown>[];\n buckets.push(...data);\n this.logger.info('fetched page', {\n resource: phase,\n page: pageCount,\n items: data.length,\n });\n if (nextUrl === null) {\n break;\n }\n pageUrl = nextUrl;\n }\n\n await this.writePhase(storage, phase, buckets);\n this.logger.info('resource done', {\n resource: phase,\n pages: pageCount,\n items: buckets.length,\n duration_ms: Date.now() - phaseStart,\n });\n }\n\n return { done: true };\n }\n\n private async fetchAnyPhasePage(\n phase: AnthropicPhase,\n initialUrl: string,\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<{\n parsed: { data: BucketPage<unknown>[] };\n nextUrl: string | null;\n }> {\n switch (phase) {\n case 'usage_messages':\n return this.fetchPhasePage(\n phase,\n usageResponseSchema,\n initialUrl,\n page,\n signal,\n );\n case 'cost_report':\n return this.fetchPhasePage(\n phase,\n costResponseSchema,\n initialUrl,\n page,\n signal,\n );\n }\n }\n\n private async writePhase(\n storage: StorageHandle,\n phase: AnthropicPhase,\n buckets: BucketPage<unknown>[],\n ): Promise<void> {\n switch (phase) {\n case 'usage_messages': {\n const samples = buildUsageSamples(buckets as BucketPage<UsageResult>[]);\n await storage.metrics(samples.inputTokens, {\n names: ['anthropic_input_tokens'],\n });\n await storage.metrics(samples.outputTokens, {\n names: ['anthropic_output_tokens'],\n });\n await storage.metrics(samples.cacheReadTokens, {\n names: ['anthropic_cache_read_tokens'],\n });\n await storage.metrics(samples.cacheCreationTokens, {\n names: ['anthropic_cache_creation_tokens'],\n });\n await storage.metrics(samples.webSearchRequests, {\n names: ['anthropic_web_search_requests'],\n });\n return;\n }\n case 'cost_report': {\n const samples = buildCostSamples(buckets as BucketPage<CostResult>[]);\n await storage.metrics(samples, { names: ['anthropic_cost_usd'] });\n return;\n }\n }\n }\n}\n\nexport type { PageResponse, BucketPage, UsageResult, CostResult };\n","import { AnthropicConnector } from './anthropic';\n\nexport {\n AnthropicConnector,\n anthropicResources as resources,\n buildCostSamples,\n buildUsageSamples,\n configFields,\n doc,\n getUsageWindow,\n id,\n} from './anthropic';\nexport type {\n AnthropicResource,\n AnthropicSettings,\n BucketPage,\n CostResult,\n PageResponse,\n UsageResult,\n} from './anthropic';\nexport default AnthropicConnector;\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rawdash/connector-anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Rawdash connector for Anthropic — daily token usage and spend from the Anthropic Admin API (usage and cost reports)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"zod": "^4.4.3",
|
|
27
|
-
"@rawdash/core": "0.
|
|
27
|
+
"@rawdash/core": "0.28.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"fast-check": "^4.8.0",
|