@coreplane/switchboard 1.221.1 → 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 +117 -3
- 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
|
@@ -11840,7 +11840,10 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11840
11840
|
if (row.workflowName in workflowNames) workflowsUsd += usd;
|
|
11841
11841
|
}
|
|
11842
11842
|
byResource.workflows += workflowsUsd;
|
|
11843
|
-
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);
|
|
11844
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;
|
|
11845
11848
|
return {
|
|
11846
11849
|
date,
|
|
@@ -11854,6 +11857,8 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11854
11857
|
workflowsUsd,
|
|
11855
11858
|
cloudUsd: cloudUsd2,
|
|
11856
11859
|
llmUsd: llmUsd2,
|
|
11860
|
+
llmEstimated,
|
|
11861
|
+
llmUnpricedTokens,
|
|
11857
11862
|
total: cloudUsd2 + llmUsd2
|
|
11858
11863
|
};
|
|
11859
11864
|
});
|
|
@@ -11870,6 +11875,20 @@ function buildCostReport(group, cfg, usage, llm, range) {
|
|
|
11870
11875
|
attribution
|
|
11871
11876
|
};
|
|
11872
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
|
+
}
|
|
11873
11892
|
function resolveRange(daysParam, now = new Date(systemClock())) {
|
|
11874
11893
|
const parsed = daysParam === null ? NaN : Number(daysParam);
|
|
11875
11894
|
const days = Number.isInteger(parsed) ? Math.min(MAX_DAYS, Math.max(1, parsed)) : DEFAULT_DAYS;
|
|
@@ -11899,7 +11918,7 @@ function createCostsService(cfg, cloudflare, llm, now = () => new Date(systemClo
|
|
|
11899
11918
|
}
|
|
11900
11919
|
};
|
|
11901
11920
|
}
|
|
11902
|
-
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;
|
|
11903
11922
|
var init_costs = __esm({
|
|
11904
11923
|
"../../src/core/costs.ts"() {
|
|
11905
11924
|
"use strict";
|
|
@@ -11949,6 +11968,26 @@ var init_costs = __esm({
|
|
|
11949
11968
|
r2: 0,
|
|
11950
11969
|
workflows: 0
|
|
11951
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}$/;
|
|
11952
11991
|
DEFAULT_DAYS = 30;
|
|
11953
11992
|
MAX_DAYS = 90;
|
|
11954
11993
|
NullLlmCostSource = class {
|
|
@@ -12062,8 +12101,10 @@ var init_costs = __esm({
|
|
|
12062
12101
|
}
|
|
12063
12102
|
};
|
|
12064
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";
|
|
12065
12105
|
ANTHROPIC_VERSION = "2023-06-01";
|
|
12066
12106
|
MAX_COST_PAGES = 20;
|
|
12107
|
+
MAX_ESTIMATED_DAYS = 3;
|
|
12067
12108
|
AnthropicCostReportSource = class {
|
|
12068
12109
|
adminKey;
|
|
12069
12110
|
fetchImpl;
|
|
@@ -12072,7 +12113,79 @@ var init_costs = __esm({
|
|
|
12072
12113
|
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
12073
12114
|
}
|
|
12074
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) {
|
|
12075
12187
|
const rows = [];
|
|
12188
|
+
let closedThrough = null;
|
|
12076
12189
|
let page2 = null;
|
|
12077
12190
|
for (let i = 0; ; i++) {
|
|
12078
12191
|
if (i >= MAX_COST_PAGES)
|
|
@@ -12094,6 +12207,7 @@ var init_costs = __esm({
|
|
|
12094
12207
|
const body = await res.json();
|
|
12095
12208
|
for (const bucket of body.data ?? []) {
|
|
12096
12209
|
const date = str2(bucket.starting_at).slice(0, 10);
|
|
12210
|
+
if (closedThrough === null || date > closedThrough) closedThrough = date;
|
|
12097
12211
|
for (const r of bucket.results ?? []) {
|
|
12098
12212
|
if (r.currency !== "USD") throw new Error(`anthropic cost_report: unexpected currency ${r.currency ?? "?"}`);
|
|
12099
12213
|
const cents = Number(r.amount);
|
|
@@ -12104,7 +12218,7 @@ var init_costs = __esm({
|
|
|
12104
12218
|
if (!body.has_more || !body.next_page) break;
|
|
12105
12219
|
page2 = body.next_page;
|
|
12106
12220
|
}
|
|
12107
|
-
return rows;
|
|
12221
|
+
return { rows, closedThrough };
|
|
12108
12222
|
}
|
|
12109
12223
|
};
|
|
12110
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.";
|
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};
|