@coreplane/switchboard 1.221.0 → 1.222.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/package-lock.json +3 -3
- package/dist/assets/package.json +1 -1
- package/dist/assets/source.json +3 -3
- package/dist/assets/web/dist/.vite/manifest.json +20 -20
- package/dist/assets/web/dist/assets/CostsPage-C-ximW1N.js +2 -0
- package/dist/assets/web/dist/assets/{ResidentDetailPage-iqyj3Kpt.js → ResidentDetailPage-BTg4oFcn.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-BiECMcX5.js → ResidentsIndexPage-Dr2qkjKI.js} +1 -1
- package/dist/assets/web/dist/assets/{RunRoutePage-YCWYYZkj.js → RunRoutePage-CTbnfyBQ.js} +3 -3
- package/dist/assets/web/dist/assets/{RunsIndexPage-BX6231bA.js → RunsIndexPage-DEkZXNnw.js} +1 -1
- package/dist/assets/web/dist/assets/{ScheduledPage-ibRdZaDS.js → ScheduledPage-wA7HE6UW.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-W2x3d782.js → StatusDot-7ojvQlTS.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-BLRVgG37.js → Tooltip-Cx88lWUW.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-C3C34ZMu.js → dist-B85zXO-d.js} +1 -1
- package/dist/assets/web/dist/assets/{main-B9dN-Wec.js → main-BdoqEBpN.js} +2 -2
- package/dist/assets/web/dist/assets/main-C1tNx19B.css +1 -0
- package/dist/cli.js +129 -8
- package/package.json +1 -1
- package/dist/assets/web/dist/assets/CostsPage-DGSE48l1.js +0 -1
- package/dist/assets/web/dist/assets/main-DCH3Mezs.css +0 -1
package/dist/cli.js
CHANGED
|
@@ -356,13 +356,14 @@ function amzDate(now) {
|
|
|
356
356
|
function encodeKey(key) {
|
|
357
357
|
return key.split("/").map(encodeURIComponent).join("/");
|
|
358
358
|
}
|
|
359
|
-
var PRESIGN_TTL_SECONDS, R2ArtifactStore;
|
|
359
|
+
var PRESIGN_TTL_SECONDS, IDENTITY, R2ArtifactStore;
|
|
360
360
|
var init_store = __esm({
|
|
361
361
|
"../../src/artifacts/store.ts"() {
|
|
362
362
|
"use strict";
|
|
363
363
|
init_clock();
|
|
364
364
|
init_config();
|
|
365
365
|
PRESIGN_TTL_SECONDS = ARTIFACT_DEFAULTS.presignTtlSeconds;
|
|
366
|
+
IDENTITY = { "accept-encoding": "identity" };
|
|
366
367
|
R2ArtifactStore = class {
|
|
367
368
|
bucket;
|
|
368
369
|
client;
|
|
@@ -402,7 +403,7 @@ var init_store = __esm({
|
|
|
402
403
|
return this.presign(key, "GET");
|
|
403
404
|
}
|
|
404
405
|
async head(key) {
|
|
405
|
-
const signed = await this.client.sign(new Request(this.objectUrl(key), { method: "HEAD" }), {
|
|
406
|
+
const signed = await this.client.sign(new Request(this.objectUrl(key), { method: "HEAD", headers: IDENTITY }), {
|
|
406
407
|
aws: { datetime: amzDate(this.clock()) }
|
|
407
408
|
});
|
|
408
409
|
const res = await this.fetchImpl(signed);
|
|
@@ -416,7 +417,7 @@ var init_store = __esm({
|
|
|
416
417
|
return { size, contentType: res.headers.get("content-type") ?? "application/octet-stream" };
|
|
417
418
|
}
|
|
418
419
|
async get(key) {
|
|
419
|
-
const signed = await this.client.sign(new Request(this.objectUrl(key), { method: "GET" }), {
|
|
420
|
+
const signed = await this.client.sign(new Request(this.objectUrl(key), { method: "GET", headers: IDENTITY }), {
|
|
420
421
|
aws: { datetime: amzDate(this.clock()) }
|
|
421
422
|
});
|
|
422
423
|
const res = await this.fetchImpl(signed);
|
|
@@ -11839,7 +11840,10 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11839
11840
|
if (row.workflowName in workflowNames) workflowsUsd += usd;
|
|
11840
11841
|
}
|
|
11841
11842
|
byResource.workflows += workflowsUsd;
|
|
11842
|
-
const
|
|
11843
|
+
const llmRows = llm && cfg.anthropicWorkspaceId ? llm.filter((r) => r.date === date && r.workspaceId === cfg.anthropicWorkspaceId) : [];
|
|
11844
|
+
const llmUsd2 = llmRows.reduce((s, r) => s + r.amountUsd, 0);
|
|
11845
|
+
const llmEstimated = llmRows.some((r) => r.estimated === true);
|
|
11846
|
+
const llmUnpricedTokens = llmRows.reduce((s, r) => s + (r.unpricedTokens ?? 0), 0);
|
|
11843
11847
|
const cloudUsd2 = Object.values(containers).reduce((s, c) => s + c.total, 0) + Object.values(durableObjects).reduce((s, v) => s + v, 0) + doRequestsUsd + doRowsUsd + doStorageUsd + workersUsd + r2Usd + workflowsUsd;
|
|
11844
11848
|
return {
|
|
11845
11849
|
date,
|
|
@@ -11853,6 +11857,8 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11853
11857
|
workflowsUsd,
|
|
11854
11858
|
cloudUsd: cloudUsd2,
|
|
11855
11859
|
llmUsd: llmUsd2,
|
|
11860
|
+
llmEstimated,
|
|
11861
|
+
llmUnpricedTokens,
|
|
11856
11862
|
total: cloudUsd2 + llmUsd2
|
|
11857
11863
|
};
|
|
11858
11864
|
});
|
|
@@ -11869,6 +11875,20 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11869
11875
|
attribution
|
|
11870
11876
|
};
|
|
11871
11877
|
}
|
|
11878
|
+
function anthropicPriceOf(modelId) {
|
|
11879
|
+
const exact = ANTHROPIC_PRICES[modelId];
|
|
11880
|
+
if (exact) return exact;
|
|
11881
|
+
for (const family of Object.keys(ANTHROPIC_PRICES)) {
|
|
11882
|
+
if (modelId.startsWith(family) && DATED_RELEASE_SUFFIX.test(modelId.slice(family.length)))
|
|
11883
|
+
return ANTHROPIC_PRICES[family];
|
|
11884
|
+
}
|
|
11885
|
+
return void 0;
|
|
11886
|
+
}
|
|
11887
|
+
function anthropicTokensCostUsd(modelId, t) {
|
|
11888
|
+
const p = anthropicPriceOf(modelId);
|
|
11889
|
+
if (!p) return void 0;
|
|
11890
|
+
return (t.uncachedInput * p.input + t.output * p.output + t.cacheRead * p.cacheRead + t.cacheWrite5m * p.cacheWrite5m + t.cacheWrite1h * p.cacheWrite1h) / 1e6;
|
|
11891
|
+
}
|
|
11872
11892
|
function resolveRange(daysParam, now = new Date(systemClock())) {
|
|
11873
11893
|
const parsed = daysParam === null ? NaN : Number(daysParam);
|
|
11874
11894
|
const days = Number.isInteger(parsed) ? Math.min(MAX_DAYS, Math.max(1, parsed)) : DEFAULT_DAYS;
|
|
@@ -11898,7 +11918,7 @@ function createCostsService(cfg, cloudflare, llm, now = () => new Date(systemClo
|
|
|
11898
11918
|
}
|
|
11899
11919
|
};
|
|
11900
11920
|
}
|
|
11901
|
-
var DEFAULT_CF_TOKEN_ENV, DEFAULT_ANTHROPIC_ADMIN_ENV, CLOUDFLARE_PRICES, GIB, GB, DAYS_PER_MONTH, TEMPLATE_BUCKET_NAMES, TEMPLATE_WORKFLOW_NAMES, emptySplit, DEFAULT_DAYS, MAX_DAYS, NullLlmCostSource, CF_GRAPHQL, CF_USAGE_QUERY, WORKFLOW_STEP_EVENTS, num2, str2, CloudflareGraphqlUsageSource, ANTHROPIC_COST_REPORT, ANTHROPIC_VERSION, MAX_COST_PAGES, AnthropicCostReportSource, COSTS_OFF_MESSAGE, NullCostsService;
|
|
11921
|
+
var DEFAULT_CF_TOKEN_ENV, DEFAULT_ANTHROPIC_ADMIN_ENV, CLOUDFLARE_PRICES, GIB, GB, DAYS_PER_MONTH, TEMPLATE_BUCKET_NAMES, TEMPLATE_WORKFLOW_NAMES, emptySplit, ANTHROPIC_PRICES, DATED_RELEASE_SUFFIX, DEFAULT_DAYS, MAX_DAYS, NullLlmCostSource, CF_GRAPHQL, CF_USAGE_QUERY, WORKFLOW_STEP_EVENTS, num2, str2, CloudflareGraphqlUsageSource, ANTHROPIC_COST_REPORT, ANTHROPIC_USAGE_REPORT, ANTHROPIC_VERSION, MAX_COST_PAGES, MAX_ESTIMATED_DAYS, AnthropicCostReportSource, COSTS_OFF_MESSAGE, NullCostsService;
|
|
11902
11922
|
var init_costs = __esm({
|
|
11903
11923
|
"../../src/core/costs.ts"() {
|
|
11904
11924
|
"use strict";
|
|
@@ -11948,6 +11968,26 @@ var init_costs = __esm({
|
|
|
11948
11968
|
r2: 0,
|
|
11949
11969
|
workflows: 0
|
|
11950
11970
|
});
|
|
11971
|
+
ANTHROPIC_PRICES = {
|
|
11972
|
+
"claude-fable-5-1": { input: 10, output: 50, cacheWrite5m: 12.5, cacheWrite1h: 20, cacheRead: 0.25 },
|
|
11973
|
+
"claude-mythos-5-1": { input: 10, output: 50, cacheWrite5m: 12.5, cacheWrite1h: 20, cacheRead: 0.25 },
|
|
11974
|
+
"claude-fable-5": { input: 10, output: 50, cacheWrite5m: 12.5, cacheWrite1h: 20, cacheRead: 1 },
|
|
11975
|
+
"claude-mythos-5": { input: 10, output: 50, cacheWrite5m: 12.5, cacheWrite1h: 20, cacheRead: 1 },
|
|
11976
|
+
"claude-opus-5": { input: 5, output: 25, cacheWrite5m: 6.25, cacheWrite1h: 10, cacheRead: 0.5 },
|
|
11977
|
+
"claude-opus-4-8": { input: 5, output: 25, cacheWrite5m: 6.25, cacheWrite1h: 10, cacheRead: 0.5 },
|
|
11978
|
+
"claude-opus-4-7": { input: 5, output: 25, cacheWrite5m: 6.25, cacheWrite1h: 10, cacheRead: 0.5 },
|
|
11979
|
+
"claude-opus-4-6": { input: 5, output: 25, cacheWrite5m: 6.25, cacheWrite1h: 10, cacheRead: 0.5 },
|
|
11980
|
+
"claude-opus-4-5": { input: 5, output: 25, cacheWrite5m: 6.25, cacheWrite1h: 10, cacheRead: 0.5 },
|
|
11981
|
+
"claude-opus-4-1": { input: 15, output: 75, cacheWrite5m: 18.75, cacheWrite1h: 30, cacheRead: 1.5 },
|
|
11982
|
+
"claude-opus-4": { input: 15, output: 75, cacheWrite5m: 18.75, cacheWrite1h: 30, cacheRead: 1.5 },
|
|
11983
|
+
"claude-sonnet-5": { input: 2, output: 10, cacheWrite5m: 2.5, cacheWrite1h: 4, cacheRead: 0.2 },
|
|
11984
|
+
"claude-sonnet-4-6": { input: 3, output: 15, cacheWrite5m: 3.75, cacheWrite1h: 6, cacheRead: 0.3 },
|
|
11985
|
+
"claude-sonnet-4-5": { input: 3, output: 15, cacheWrite5m: 3.75, cacheWrite1h: 6, cacheRead: 0.3 },
|
|
11986
|
+
"claude-sonnet-4": { input: 3, output: 15, cacheWrite5m: 3.75, cacheWrite1h: 6, cacheRead: 0.3 },
|
|
11987
|
+
"claude-haiku-4-5": { input: 1, output: 5, cacheWrite5m: 1.25, cacheWrite1h: 2, cacheRead: 0.1 },
|
|
11988
|
+
"claude-haiku-3-5": { input: 0.8, output: 4, cacheWrite5m: 1, cacheWrite1h: 1.6, cacheRead: 0.08 }
|
|
11989
|
+
};
|
|
11990
|
+
DATED_RELEASE_SUFFIX = /^-\d{8}$/;
|
|
11951
11991
|
DEFAULT_DAYS = 30;
|
|
11952
11992
|
MAX_DAYS = 90;
|
|
11953
11993
|
NullLlmCostSource = class {
|
|
@@ -12061,8 +12101,10 @@ var init_costs = __esm({
|
|
|
12061
12101
|
}
|
|
12062
12102
|
};
|
|
12063
12103
|
ANTHROPIC_COST_REPORT = "https://api.anthropic.com/v1/organizations/cost_report";
|
|
12104
|
+
ANTHROPIC_USAGE_REPORT = "https://api.anthropic.com/v1/organizations/usage_report/messages";
|
|
12064
12105
|
ANTHROPIC_VERSION = "2023-06-01";
|
|
12065
12106
|
MAX_COST_PAGES = 20;
|
|
12107
|
+
MAX_ESTIMATED_DAYS = 3;
|
|
12066
12108
|
AnthropicCostReportSource = class {
|
|
12067
12109
|
adminKey;
|
|
12068
12110
|
fetchImpl;
|
|
@@ -12071,7 +12113,79 @@ var init_costs = __esm({
|
|
|
12071
12113
|
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
12072
12114
|
}
|
|
12073
12115
|
async fetchDailyCost(range) {
|
|
12116
|
+
const report2 = await this.fetchCostReport(range);
|
|
12117
|
+
const open2 = eachDay(range).filter((date) => report2.closedThrough === null || date > report2.closedThrough);
|
|
12118
|
+
const estimated = await Promise.all(open2.slice(-MAX_ESTIMATED_DAYS).map((date) => this.estimateDay(date)));
|
|
12119
|
+
return [...report2.rows, ...estimated.flat()];
|
|
12120
|
+
}
|
|
12121
|
+
/** The hourly usage report for one day, summed per workspace × model and
|
|
12122
|
+
* priced at list; one row per workspace, `estimated`, with the tokens of
|
|
12123
|
+
* any model the price table does not know reported as `unpricedTokens`. */
|
|
12124
|
+
async estimateDay(date) {
|
|
12125
|
+
const perWorkspace = /* @__PURE__ */ new Map();
|
|
12126
|
+
let page2 = null;
|
|
12127
|
+
for (let i = 0; ; i++) {
|
|
12128
|
+
if (i >= MAX_COST_PAGES)
|
|
12129
|
+
throw new Error(
|
|
12130
|
+
`anthropic usage_report: more than ${MAX_COST_PAGES} pages for ${date}; refusing a truncated estimate`
|
|
12131
|
+
);
|
|
12132
|
+
const url = new URL(ANTHROPIC_USAGE_REPORT);
|
|
12133
|
+
url.searchParams.set("starting_at", `${date}T00:00:00Z`);
|
|
12134
|
+
url.searchParams.set("ending_at", `${addDays2(date, 1)}T00:00:00Z`);
|
|
12135
|
+
url.searchParams.set("bucket_width", "1h");
|
|
12136
|
+
url.searchParams.append("group_by[]", "workspace_id");
|
|
12137
|
+
url.searchParams.append("group_by[]", "model");
|
|
12138
|
+
url.searchParams.set("limit", "24");
|
|
12139
|
+
if (page2) url.searchParams.set("page", page2);
|
|
12140
|
+
const res = await this.fetchImpl(url.toString(), {
|
|
12141
|
+
headers: { "x-api-key": this.adminKey, "anthropic-version": ANTHROPIC_VERSION }
|
|
12142
|
+
});
|
|
12143
|
+
if (res.status !== 200)
|
|
12144
|
+
throw new Error(`anthropic usage_report ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
12145
|
+
const body = await res.json();
|
|
12146
|
+
for (const bucket of body.data ?? []) {
|
|
12147
|
+
for (const r of bucket.results ?? []) {
|
|
12148
|
+
const ws = r.workspace_id ?? null;
|
|
12149
|
+
const byModel = perWorkspace.get(ws) ?? /* @__PURE__ */ new Map();
|
|
12150
|
+
const model = str2(r.model);
|
|
12151
|
+
const t = byModel.get(model) ?? {
|
|
12152
|
+
uncachedInput: 0,
|
|
12153
|
+
output: 0,
|
|
12154
|
+
cacheRead: 0,
|
|
12155
|
+
cacheWrite5m: 0,
|
|
12156
|
+
cacheWrite1h: 0
|
|
12157
|
+
};
|
|
12158
|
+
t.uncachedInput += num2(r.uncached_input_tokens);
|
|
12159
|
+
t.output += num2(r.output_tokens);
|
|
12160
|
+
t.cacheRead += num2(r.cache_read_input_tokens);
|
|
12161
|
+
t.cacheWrite5m += num2(r.cache_creation?.ephemeral_5m_input_tokens);
|
|
12162
|
+
t.cacheWrite1h += num2(r.cache_creation?.ephemeral_1h_input_tokens);
|
|
12163
|
+
byModel.set(model, t);
|
|
12164
|
+
perWorkspace.set(ws, byModel);
|
|
12165
|
+
}
|
|
12166
|
+
}
|
|
12167
|
+
if (!body.has_more || !body.next_page) break;
|
|
12168
|
+
page2 = body.next_page;
|
|
12169
|
+
}
|
|
12170
|
+
const out = [];
|
|
12171
|
+
for (const [workspaceId, byModel] of perWorkspace) {
|
|
12172
|
+
let amountUsd = 0;
|
|
12173
|
+
let unpricedTokens = 0;
|
|
12174
|
+
for (const [model, t] of byModel) {
|
|
12175
|
+
const usd = anthropicTokensCostUsd(model, t);
|
|
12176
|
+
if (usd === void 0)
|
|
12177
|
+
unpricedTokens += t.uncachedInput + t.output + t.cacheRead + t.cacheWrite5m + t.cacheWrite1h;
|
|
12178
|
+
else amountUsd += usd;
|
|
12179
|
+
}
|
|
12180
|
+
out.push({ date, workspaceId, amountUsd, estimated: true, unpricedTokens });
|
|
12181
|
+
}
|
|
12182
|
+
return out;
|
|
12183
|
+
}
|
|
12184
|
+
/** Every page of the cost report for the range, plus the last day it has a
|
|
12185
|
+
* bucket for (null when it has none in the range). */
|
|
12186
|
+
async fetchCostReport(range) {
|
|
12074
12187
|
const rows = [];
|
|
12188
|
+
let closedThrough = null;
|
|
12075
12189
|
let page2 = null;
|
|
12076
12190
|
for (let i = 0; ; i++) {
|
|
12077
12191
|
if (i >= MAX_COST_PAGES)
|
|
@@ -12093,6 +12207,7 @@ var init_costs = __esm({
|
|
|
12093
12207
|
const body = await res.json();
|
|
12094
12208
|
for (const bucket of body.data ?? []) {
|
|
12095
12209
|
const date = str2(bucket.starting_at).slice(0, 10);
|
|
12210
|
+
if (closedThrough === null || date > closedThrough) closedThrough = date;
|
|
12096
12211
|
for (const r of bucket.results ?? []) {
|
|
12097
12212
|
if (r.currency !== "USD") throw new Error(`anthropic cost_report: unexpected currency ${r.currency ?? "?"}`);
|
|
12098
12213
|
const cents = Number(r.amount);
|
|
@@ -12103,7 +12218,7 @@ var init_costs = __esm({
|
|
|
12103
12218
|
if (!body.has_more || !body.next_page) break;
|
|
12104
12219
|
page2 = body.next_page;
|
|
12105
12220
|
}
|
|
12106
|
-
return rows;
|
|
12221
|
+
return { rows, closedThrough };
|
|
12107
12222
|
}
|
|
12108
12223
|
};
|
|
12109
12224
|
COSTS_OFF_MESSAGE = "Cost reporting isn't configured \u2014 set costs.cloudflareAccountId + costs.groups in config and the CF_ANALYTICS_TOKEN secret to enable this view.";
|
|
@@ -31564,8 +31679,13 @@ var init_bridge2 = __esm({
|
|
|
31564
31679
|
break;
|
|
31565
31680
|
case "message_end":
|
|
31566
31681
|
if (isRecord3(event.message)) {
|
|
31567
|
-
|
|
31568
|
-
|
|
31682
|
+
if (event.message.role === "assistant") {
|
|
31683
|
+
const assistant = event.message;
|
|
31684
|
+
this.onAssistant(assistant, out);
|
|
31685
|
+
if (assistant.stopReason !== "error") out.message = event.message;
|
|
31686
|
+
} else {
|
|
31687
|
+
out.message = event.message;
|
|
31688
|
+
}
|
|
31569
31689
|
}
|
|
31570
31690
|
break;
|
|
31571
31691
|
case "tool_execution_start":
|
|
@@ -31911,6 +32031,7 @@ var init_mirror = __esm({
|
|
|
31911
32031
|
if (!this.deps.onStep) return;
|
|
31912
32032
|
const chat = chatMessageOf(message3);
|
|
31913
32033
|
if (!chat) return;
|
|
32034
|
+
if (chat.content.length === 0) return;
|
|
31914
32035
|
if (chat.role === "user") {
|
|
31915
32036
|
if (!this.seedEchoed && !chat.content.some((p) => p.type === "tool_result")) {
|
|
31916
32037
|
this.seedEchoed = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreplane/switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.222.0",
|
|
4
4
|
"description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://openswitchboard.dev",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./AppShell-lYVcj-k7.js";import{Ci as t,Lr as n,Xt as r,_n as i,cn as a,gn as o,ir as s,ln as c,on as l,r as u,sn as d,un as f,ur as p,vi as m,wi as h,xi as g,yn as _}from"./seed-DeKSHrt2.js";var v=`Durable Objects`,y=`Workers · storage · R2`,b=`LLM (Anthropic)`,x=(e,t=2)=>`$${e.toFixed(t)}`,S=e=>e.workersUsd+e.doRowsUsd+e.doStorageUsd+e.r2Usd+e.workflowsUsd;function ee(e){let t=[];for(let n of e.days)for(let e of Object.keys(n.containers))t.includes(e)||t.push(e);return e.days.some(e=>Object.keys(e.durableObjects).length>0)&&t.push(v),e.days.some(e=>S(e)>0)&&t.push(y),e.llmAvailable&&t.push(b),t}function C(e,t){return t===`Durable Objects`?Object.values(e.durableObjects).reduce((e,t)=>e+t,0)+e.doRequestsUsd:t===`Workers · storage · R2`?S(e):t===`LLM (Anthropic)`?e.llmUsd:e.containers[t]?.total??0}function w(e){let t=e.range.partialLastDay?e.days.slice(0,-1):e.days,n=t[t.length-1],r=t.slice(-7),i=r.length?r.reduce((e,t)=>e+t.total,0)/r.length:0,a=e.totals.total>0?Math.round(e.totals.llmUsd/e.totals.total*100):0,o=e.account.cloudUsd>0?Math.round(e.totals.cloudUsd/e.account.cloudUsd*100):0;return{...n?{yesterday:{date:n.date,total:n.total}}:{},avg7:i,projectedMonth:i*30.4,llmShare:a,accountShare:o}}function T(e,t){let n={t:12,r:12,b:30,l:48},r=960-n.l-n.r,i=260-n.t-n.b,a=e.days,o=Math.max(1e-9,...a.map(e=>e.total))*1.08,s=r/Math.max(1,a.length),c=Math.min(10,s*.28),l=e=>n.t+i-e/o*i,u=Array.from({length:5},(e,t)=>{let n=o/4*t;return{y:Number(l(n).toFixed(1)),label:x(n)}}),d=[],f=[];return a.forEach((e,r)=>{let i=0,o=n.l+r*s+c/2,u=s-c;t.forEach((t,n)=>{let r=C(e,t);if(r<=0)return;let a=l(i+r),s=l(i),c=Math.max(0,s-a-2);d.push({seriesIndex:n,x:Number(o.toFixed(1)),y:Number(a.toFixed(1)),width:Number(u.toFixed(1)),height:Number(c.toFixed(1)),title:`${e.date} · ${t} · ${x(r)}`}),i+=r}),(a.length<=16||r%Math.ceil(a.length/16)===0)&&f.push({x:Number((o+u/2).toFixed(1)),label:e.date.slice(5)})}),{width:960,height:260,gridLines:u,segments:d,dayLabels:f,axisY:Number(l(0).toFixed(1)),marginLeft:n.l,marginRight:n.r}}function E(e){let t=e.totals.byResource,n=[[`Memory (provisioned while awake)`,t.memory],[`vCPU (active use only)`,t.cpu],[`Durable Object duration + requests`,t.durableObjects],[`Disk (provisioned while awake)`,t.disk],[`Workers requests + CPU`,t.workers],[`Durable Object SQLite rows`,t.doRows],[`Durable Object SQLite storage`,t.doStorage],[`R2 storage + operations`,t.r2],[`Workflow steps + state`,t.workflows]],r=n.reduce((e,t)=>e+t[1],0)||1;return n.map(([e,t])=>({label:e,usd:t,percent:t/r*100}))}var D=[`fill-[#4478b8] dark:fill-[#7aa7e0]`,`fill-[#c8823b] dark:fill-[#e0a95a]`,`fill-[#4c8c57] dark:fill-[#6fae7a]`,`fill-[#b8963e] dark:fill-[#d4b45a]`,`fill-[#b0568c] dark:fill-[#d489b8]`,`fill-[#6b7bcc] dark:fill-[#98a5e6]`,`fill-[#d05252] dark:fill-[#e07a74]`,`fill-[#3e8e96] dark:fill-[#6fb9c0]`],O=[`bg-[#4478b8] dark:bg-[#7aa7e0]`,`bg-[#c8823b] dark:bg-[#e0a95a]`,`bg-[#4c8c57] dark:bg-[#6fae7a]`,`bg-[#b8963e] dark:bg-[#d4b45a]`,`bg-[#b0568c] dark:bg-[#d489b8]`,`bg-[#6b7bcc] dark:bg-[#98a5e6]`,`bg-[#d05252] dark:bg-[#e07a74]`,`bg-[#3e8e96] dark:bg-[#6fb9c0]`],k={class:`overflow-x-auto`},A=[`viewBox`],j=[`x1`,`x2`,`y1`,`y2`],M=[`x`,`y`],N=[`x`,`y`,`width`,`height`],P=[`x`,`y`],F=[`x1`,`x2`,`y1`,`y2`],I=_({__name:`CostChart`,props:{report:{},series:{}},setup(e){let t=e,n=l(()=>T(t.report,t.series));return(e,t)=>(s(),f(`div`,k,[(s(),f(`svg`,{class:`block h-auto w-full font-mono`,viewBox:`0 0 ${n.value.width} ${n.value.height}`,role:`img`,"aria-label":`Daily cost, stacked by component`},[(s(!0),f(r,null,p(n.value.gridLines,(e,t)=>(s(),f(r,{key:`g${t}`},[d(`line`,{class:`stroke-(--ui-border-muted)`,x1:n.value.marginLeft,x2:n.value.width-n.value.marginRight,y1:e.y,y2:e.y},null,8,j),d(`text`,{class:`fill-(--ui-text-dimmed) text-[11px] tabular-nums`,x:n.value.marginLeft-8,y:e.y+4,"text-anchor":`end`},h(e.label),9,M)],64))),128)),(s(!0),f(r,null,p(n.value.segments,(e,t)=>(s(),f(`rect`,{key:`s${t}`,class:g([`seg hover:opacity-85`,m(D)[e.seriesIndex%m(D).length]]),x:e.x,y:e.y,width:e.width,height:e.height},[d(`title`,null,h(e.title),1)],10,N))),128)),(s(!0),f(r,null,p(n.value.dayLabels,(e,t)=>(s(),f(`text`,{key:`d${t}`,class:`fill-(--ui-text-dimmed) text-[11px]`,x:e.x,y:n.value.height-10,"text-anchor":`middle`},h(e.label),9,P))),128)),d(`line`,{class:`stroke-(--ui-border)`,x1:n.value.marginLeft,x2:n.value.width-n.value.marginRight,y1:n.value.axisY,y2:n.value.axisY},null,8,F)],8,A))]))}}),L={class:`text-xs text-muted`},R={key:1,class:`text-highlighted`},z=[`href`],B={class:`mb-4 flex flex-wrap items-center gap-x-4 gap-y-2`},V={key:0,class:`flex items-center gap-1`,"aria-label":`Cost groups`},H={key:0,class:`rounded-md bg-accented px-2.5 py-1 text-xs font-medium text-highlighted`,"aria-current":`page`},U=[`href`],W={class:`font-mono text-sm tabular-nums text-muted`},G={class:`mb-5 grid grid-cols-[repeat(auto-fit,minmax(190px,1fr))] gap-3`},K={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},q={class:`font-mono text-2xl font-medium tabular-nums`},J={class:`text-xs text-muted`},Y={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},X={class:`font-mono text-2xl font-medium tabular-nums`},Z={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},Q={class:`font-mono text-2xl font-medium tabular-nums`},te={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},ne={class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},re={class:`font-mono text-2xl font-medium tabular-nums`},ie={class:`text-xs text-muted`},ae={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},oe={class:`font-mono text-2xl font-medium tabular-nums`},se={class:`text-xs text-muted`},ce={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},le={class:`flex flex-wrap items-baseline justify-between gap-x-4 gap-y-2`},ue={class:`legend flex flex-wrap gap-x-4 gap-y-1.5 text-xs text-muted`},de={key:0,class:`text-xs text-warn`},fe={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},pe={class:`w-full border-collapse font-mono text-[0.8125rem] tabular-nums`},me={class:`px-2.5 py-1.5`},he={class:`px-2.5 py-1.5 text-right`},ge={class:`px-2.5 py-1.5 text-right`},_e={class:`w-2/5 px-2.5 py-1.5`},ve={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},ye={open:``},be={class:`mt-2.5 overflow-x-auto`},$={class:`data w-full min-w-[38rem] border-collapse whitespace-nowrap font-mono text-[0.8125rem] tabular-nums`},xe=[`title`],Se={key:0,class:`text-xs text-dimmed`},Ce={class:`border-b border-muted px-2.5 py-1.5 text-right font-medium`},we={class:`text-xs text-muted`},Te={class:`rounded bg-accented px-1 py-0.5`},Ee={class:`border-t border-default pt-3.5 text-xs text-dimmed`},De={class:`mt-2 grid gap-1.5`},Oe=_({__name:`CostsPage`,setup(_){let v=u(`costs`),y=l(()=>v?.report??null),b=l(()=>v?.groups??[]),S=l(()=>y.value?ee(y.value):[]),T=l(()=>y.value?w(y.value):null),D=l(()=>y.value?E(y.value):[]),k=[7,30,90];function A(e){let t=new Date(`${e}T00:00:00Z`);return Number.isNaN(t.getTime())?e:`${[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`][t.getUTCMonth()]} ${t.getUTCDate()}`}return(l,u)=>y.value&&T.value?(s(),a(e,{key:0,title:`${y.value.label} spend`,nav:`costs`},{actions:n(()=>[d(`span`,L,[(s(),f(r,null,p(k,(e,t)=>(s(),f(r,{key:e},[t>0?(s(),f(r,{key:0},[o(` · `)],64)):c(``,!0),e===y.value.range.days?(s(),f(`b`,R,h(e)+`d`,1)):(s(),f(`a`,{key:2,class:`text-primary hover:underline`,href:`/costs/${y.value.group}?days=${e}`},h(e)+`d`,9,z))],64))),64))])]),default:n(()=>[d(`div`,B,[b.value.length>1?(s(),f(`nav`,V,[(s(!0),f(r,null,p(b.value,e=>(s(),f(r,{key:e},[e===y.value.group?(s(),f(`span`,H,h(e),1)):(s(),f(`a`,{key:1,class:`rounded-md px-2.5 py-1 text-xs text-muted no-underline hover:bg-elevated hover:text-highlighted`,href:`/costs/${e}`},h(e),9,U))],64))),128))])):c(``,!0),d(`p`,W,[o(h(A(y.value.range.from))+` → `+h(A(y.value.range.to))+` · `+h(y.value.range.days)+`d`,1),y.value.range.partialLastDay?(s(),f(r,{key:0},[o(` · today partial`)],64)):c(``,!0)])]),d(`section`,G,[d(`div`,K,[u[0]||=d(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Yesterday`,-1),d(`span`,q,h(T.value.yesterday?m(x)(T.value.yesterday.total):`—`),1),d(`span`,J,h(T.value.yesterday?`${T.value.yesterday.date} · last full day`:`no full day in range`),1)]),d(`div`,Y,[u[1]||=d(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`7-day average`,-1),d(`span`,X,h(m(x)(T.value.avg7)),1),u[2]||=d(`span`,{class:`text-xs text-muted`},`per day, full days only`,-1)]),d(`div`,Z,[u[3]||=d(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Projected month`,-1),d(`span`,Q,h(m(x)(T.value.projectedMonth,0)),1),u[4]||=d(`span`,{class:`text-xs text-muted`},`7-day rate × 30.4, before plan fees and included allowances`,-1)]),d(`div`,te,[d(`span`,ne,h(y.value.llmAvailable?`LLM share`:`LLM spend`),1),d(`span`,re,h(y.value.llmAvailable?`${T.value.llmShare}%`:`—`),1),d(`span`,ie,h(y.value.llmAvailable?`of the range total`:`LLM spend not configured`),1)]),d(`div`,ae,[u[5]||=d(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Share of account`,-1),d(`span`,oe,h(T.value.accountShare)+`%`,1),d(`span`,se,h(m(x)(y.value.totals.cloudUsd))+` of `+h(m(x)(y.value.account.cloudUsd))+` Cloudflare spend in range`,1)])]),d(`section`,ce,[d(`div`,le,[u[6]||=d(`div`,null,[d(`h2`,{class:`text-[0.9375rem] font-medium`},`Daily cost`),d(`p`,{class:`text-sm text-muted`},`Stacked by component · USD list price`)],-1),d(`div`,ue,[(s(!0),f(r,null,p(S.value,(e,t)=>(s(),f(`span`,{key:e,class:`inline-flex items-center gap-1.5`},[d(`i`,{class:g([`inline-block size-2.5 rounded-xs`,m(O)[t%m(O).length]])},null,2),o(h(e),1)]))),128))])]),i(I,{report:y.value,series:S.value},null,8,[`report`,`series`]),y.value.llmAvailable?c(``,!0):(s(),f(`p`,de,[...u[7]||=[o(` LLM spend not configured — set `,-1),d(`code`,null,`ANTHROPIC_ADMIN_KEY`,-1),o(` and the group's `,-1),d(`code`,null,`anthropicWorkspaceId`,-1),o(` to layer it in. `,-1)]]))]),d(`section`,fe,[u[8]||=d(`div`,null,[d(`h2`,{class:`text-[0.9375rem] font-medium`},`What each cloud dollar buys`)],-1),d(`table`,pe,[d(`tbody`,null,[(s(!0),f(r,null,p(D.value,e=>(s(),f(`tr`,{key:e.label,class:`border-b border-muted`},[d(`td`,me,h(e.label),1),d(`td`,he,h(m(x)(e.usd)),1),d(`td`,ge,h(Math.round(e.percent))+`%`,1),d(`td`,_e,[d(`i`,{class:`block h-2.5 rounded-xs bg-primary opacity-75`,style:t({width:`${e.percent.toFixed(1)}%`})},null,4)])]))),128))])])]),d(`section`,ve,[d(`details`,ye,[u[11]||=d(`summary`,{class:`cursor-pointer text-sm text-muted`},`Table view — daily cost by component (USD)`,-1),d(`div`,be,[d(`table`,$,[d(`thead`,null,[d(`tr`,null,[u[9]||=d(`th`,{class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-left text-xs font-medium text-muted`},` Date `,-1),(s(!0),f(r,null,p(S.value,e=>(s(),f(`th`,{key:e,class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-right text-xs font-medium text-muted`},h(e),1))),128)),u[10]||=d(`th`,{class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-right text-xs font-medium text-muted`},` Total `,-1)])]),d(`tbody`,null,[(s(!0),f(r,null,p(y.value.days,e=>(s(),f(`tr`,{key:e.date},[d(`td`,{class:`border-b border-muted px-2.5 py-1.5`,title:e.date},[o(h(A(e.date))+` `,1),y.value.range.partialLastDay&&e.date===y.value.range.to?(s(),f(`span`,Se,`(partial day)`)):c(``,!0)],8,xe),(s(!0),f(r,null,p(S.value,t=>(s(),f(`td`,{key:t,class:`border-b border-muted px-2.5 py-1.5 text-right`},h(m(x)(m(C)(e,t),3)),1))),128)),d(`td`,Ce,h(m(x)(e.total,3)),1)]))),128))])])])]),d(`p`,we,[u[12]||=o(` Machine-readable twin: `,-1),d(`code`,Te,`GET /costs/`+h(y.value.group)+`.json`,1),u[13]||=o(` (same Access gate). `,-1)])]),d(`footer`,Ee,[d(`details`,null,[u[18]||=d(`summary`,{class:`cursor-pointer text-muted`},`How these numbers are computed`,-1),d(`div`,De,[u[16]||=d(`div`,null,[d(`b`,null,`Live.`),o(` Both billing sources are read live from this page — nothing cached, nothing stored. Cloudflare bills vCPU on active use only; memory and disk bill on the provisioned size for every second a container is awake. LLM spend is the Anthropic Admin API cost report for this group's workspace (gross, USD). `)],-1),u[17]||=d(`div`,null,[d(`b`,null,`Method.`),o(` Cloudflare GraphQL Analytics, every meter a Workers deployment is billed on: `),d(`code`,null,`containersUsageAdaptiveGroups`),o(` (cpuTimeSec, allocatedMemory, allocatedDisk per app per UTC day), `),d(`code`,null,`durableObjectsPeriodicGroups`),o(` (billable `),d(`code`,null,`duration`),o(` GB-s and SQLite rows read and written per namespace), `),d(`code`,null,`durableObjectsInvocationsAdaptiveGroups`),o(` (requests per namespace), `),d(`code`,null,`durableObjectsSqlStorageGroups`),o(` (bytes stored), `),d(`code`,null,`workersInvocationsAdaptive`),o(` (requests, CPU time), `),d(`code`,null,`r2StorageAdaptiveGroups`),o(` and `),d(`code`,null,`r2OperationsAdaptiveGroups`),o(` (bytes stored, class A/B operations). Prices: vCPU $0.000020/s, memory $0.0000025/GiB-s, disk $0.00000007/GB-s, DO duration $12.50 per million GB-s, DO requests $0.15/M, SQLite rows $0.001/M read and $1.00/M written, DO storage $0.20/GB-month, Workers $0.30/M requests and $0.02/M CPU-ms, R2 $0.015/GB-month, $4.50/M class A and $0.36/M class B (deletes free). Storage is the day's peak, prorated over a 30.44-day month. Gross list price — plan fees and included allowances are not subtracted; Workers Logs volume has no analytics dataset and is not priced. `)],-1),d(`div`,null,[u[14]||=d(`b`,null,`Scope.`,-1),u[15]||=o(` Attributed to this group: the Workers `,-1),d(`code`,null,h(y.value.attribution.workers.join(`, `)),1),o(`, every Durable Object namespace they host (`+h(Object.keys(y.value.attribution.durableObjectNamespaces).length)+`), the R2 buckets named after them (`+h(Object.keys(y.value.attribution.r2Buckets).length)+`), and the container apps mapped in `,1),d(`code`,null,`costs.groups.`+h(y.value.group),1),o(` (`+h(Object.keys(y.value.attribution.containerApps).length)+`). Everything else in the account is priced the same way into the account total, which is what "share of account" divides by. `,1)])])])])]),_:1},8,[`title`])):c(``,!0)}});export{Oe as default};
|