diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..0fc1870 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,71 @@ +{ + "name": "bruin-agent-resource-kit", + "owner": { + "name": "Bruin", + "url": "https://github.com/bruin-data" + }, + "description": "Example agent skills for working with a startup's data through Bruin. Sample code, provided as-is; not a supported Bruin product.", + "plugins": [ + { + "name": "bruin-agent", + "description": "Install the Bruin CLI, create a project, choose a template, connect a source and register the Bruin MCP server.", + "source": "./", + "strict": false, + "skills": [ + "./resources/bruin-agent" + ] + }, + { + "name": "startup-data-kit", + "description": "Set up a Bruin template for a startup's data and answer questions from it: revenue, marketing, product, web, AI search, finance, support, AI coding spend, sheets and Notion.", + "source": "./", + "strict": false, + "skills": [ + "./resources/startup-data-kit/ai-coding-spend", + "./resources/startup-data-kit/ai-search-visibility", + "./resources/startup-data-kit/finance-accounting", + "./resources/startup-data-kit/marketing-analytics", + "./resources/startup-data-kit/product-analytics", + "./resources/startup-data-kit/revenue-analytics", + "./resources/startup-data-kit/sheets-and-notion", + "./resources/startup-data-kit/support-analytics", + "./resources/startup-data-kit/web-analytics" + ] + }, + { + "name": "data-engineering-skills", + "description": "Keep Bruin pipelines healthy: triage failures, investigate anomalies, backfill safely, open maintenance pull requests, report what happened.", + "source": "./", + "strict": false, + "skills": [ + "./resources/data-engineering-skills/anomaly-investigate", + "./resources/data-engineering-skills/bruin-builtin-skills", + "./resources/data-engineering-skills/maintenance-pr", + "./resources/data-engineering-skills/pipeline-backfill", + "./resources/data-engineering-skills/pipeline-report", + "./resources/data-engineering-skills/pipeline-triage" + ] + }, + { + "name": "coding-agent-workflows", + "description": "Repeatable work on a codebase: customer-facing changelogs and recorded terminal demos.", + "source": "./", + "strict": false, + "skills": [ + "./resources/coding-agent-workflows/generate-changelog", + "./resources/coding-agent-workflows/record-terminal-demo" + ] + }, + { + "name": "tools", + "description": "Sample scripts an agent can shell out to, run with your own credentials: Attio CRM, blog cover images, LinkedIn enrichment via Apify.", + "source": "./", + "strict": false, + "skills": [ + "./resources/tools/attio-cli", + "./resources/tools/blog-image-generator", + "./resources/tools/linkedin-enrichment" + ] + } + ] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..70776ad --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# GitHub language statistics (Linguist). This repository is a catalogue of +# Markdown skills; the Python is sample code and tooling around them. +# https://github.com/github-linguist/linguist/blob/main/docs/overrides.md + +# Markdown is a prose language, which Linguist leaves out of the stats unless +# it is marked detectable. +*.md linguist-detectable + +# Sample scripts and the checker: excluded from the stats. +resources/**/scripts/** linguist-vendored +*.py linguist-vendored +*.py -linguist-detectable + +# Generated by sample-data/generate.py: collapsed in diffs, excluded from stats. +resources/**/sample-data/*.csv linguist-generated diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 85aa2e6..3a93dfd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,7 +16,7 @@ One or two sentences. - [ ] `name` matches the folder, `description` starts with `Use when` - [ ] `**Status:**` and `**Risk:**` line, chosen conservatively -- [ ] Listed in the root `README.md` index +- [ ] Listed in the root `README.md` index and in `.claude-plugin/marketplace.json` - [ ] Says what the tool cannot do, and what the user has to decide - [ ] No credentials, customer data or production output - [ ] Does not ask a user to paste a credential into a conversation diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 54bb970..01c3e53 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -22,8 +22,9 @@ jobs: with: python-version: "3.12" - # Frontmatter, status labels, upstream notes and their dates, index - # completeness, local links, forbidden files. No dependencies. + # Frontmatter, status labels, upstream notes and their dates, index and + # plugin manifest completeness, local links, sample data, forbidden + # files. No dependencies. - name: Validate catalogue run: ./tests/check.py diff --git a/.gitignore b/.gitignore index 81e7ffe..e594802 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,7 @@ venv/ # Local databases from trying a template. *.db *.db.wal +*.duckdb +*.duckdb.wal .DS_Store diff --git a/AGENTS.md b/AGENTS.md index 25f0d95..ac4848f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -158,12 +158,13 @@ confirm. Never write an unchecked claim as though you had checked it. Add a `**Status:**` and `**Risk:**` line under the heading. Be conservative: `experimental` unless someone other than the author has used it. Add the -resource to the index in [`README.md`](README.md); the checker fails if you do -not. +resource to the index in [`README.md`](README.md) and to its group's plugin in +[`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json); the +checker fails if you do not. Run `./tests/check.py` before finishing. No dependencies. It verifies -frontmatter, labels, upstream notes and their dates, index completeness, local -links, and forbidden files. +frontmatter, labels, upstream notes and their dates, index and plugin manifest +completeness, local links, sample data, and forbidden files. Never commit a credential, customer record or production output. `.bruin.yml`, `.env` and similar are gitignored, and both the checker and gitleaks will fail diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d50586..a76b318 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,7 +57,11 @@ The rules the checker enforces: carries a date. A file that drives no tool gets a one-line precedence note instead, saying what wins where it disagrees; the checker does not enforce that one. -- Every resource is listed in the root `README.md` index. +- Every resource is listed in the root `README.md` index, and its folder in one + plugin's `skills` list in `.claude-plugin/marketplace.json`. Both one-line + installs read that manifest, so a skill missing from it cannot be installed. +- Sample data lives in a `sample-data/` folder, is invented, and uses only + `example.com`, `example.org` or `example.net` email addresses. - Local links resolve, and no internal identifiers (Slack channel IDs, project ULIDs, service accounts) or forbidden files (`.bruin.yml`, `.env`) appear. - Files shared across a group of skills stay identical. Every @@ -142,7 +146,8 @@ prevent. ``` No dependencies. It checks frontmatter, status labels, upstream notes and their -dates, index completeness, local links, and forbidden files. +dates, index and plugin manifest completeness, local links, sample data, and +forbidden files. Then say, in the pull request: what the resource does in one sentence, what you ran to verify it, which status and risk you chose and why, and anything you diff --git a/README.md b/README.md index a884c5e..08df3cb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,45 @@ # agent-resource-kit +**Give Claude Code, Cursor and Codex your startup's data.** +[`startup-data-kit`](resources/startup-data-kit/) is a set of agent skills that +set up a maintained Bruin pipeline for revenue, marketing, product, finance or +AI coding spend, then answer questions from it without the confident wrong number. + +```bash +npx skills add bruin-data/agent-resource-kit +``` + +![The ai-coding-usage template building on fake Claude Code and Cursor data in DuckDB, then a weekly cost query](demo/ai-coding-spend.gif) + +### Try it in 2 minutes + +No credentials and no warehouse: the real `ai-coding-usage` template, fake +Claude Code and Cursor usage, DuckDB. Needs the +[Bruin CLI](https://getbruin.com/docs/bruin/getting-started/introduction/installation.html) +and git; run it in an empty folder outside any git repository. + +```bash +# 1. Get the template and the sample data +git clone --depth 1 https://github.com/bruin-data/agent-resource-kit +bruin init ai-coding-usage ai-coding-demo + +# 2. Swap the Anthropic and Cursor API assets for the fake CSVs +cp agent-resource-kit/resources/startup-data-kit/ai-coding-spend/sample-data/*.{asset.yml,csv} \ + bruin/ai-coding-demo/assets/raw/ + +# 3. Build every table on DuckDB, then query one +cd bruin +bruin run ai-coding-demo --full-refresh --workers 1 --start-date 2026-09-14 --end-date 2026-09-27 +bruin query -c duckdb-default -q "SELECT strftime(date_trunc('week', usage_date), '%Y-%m-%d') AS week, platform, CAST(SUM(total_tokens) AS BIGINT) AS tokens, ROUND(SUM(estimated_cost_usd), 2) AS est_cost_usd FROM marts.ai_coding_usage_by_user_day GROUP BY ALL ORDER BY ALL" +``` + +Then ask your agent, with the skill installed, why estimated Claude Code cost +rose in the second week. [`sample-data/`](resources/startup-data-kit/ai-coding-spend/sample-data/) +says what the data is and why each flag is there; `--full-refresh` is only safe +because the demo database is new. + +## What is here + **Open-source skills for AI agents.** Drop a folder into your project and your agent knows how to do the thing. @@ -15,13 +55,6 @@ to ask questions, work through a setup with someone, and share what you have built with these. If a skill sent your agent somewhere unhelpful, that is worth saying there as much as in an issue. -> **Example code, provided as-is.** This repository is not part of the Bruin -> platform, not a supported Bruin product, and not covered by any support -> agreement or SLA. It is documentation and sample scripts: it stores no customer -> data, holds no credentials, and has no access to any production system. Scripts -> run on your own machine, under your own credentials, configured by you. See -> [LICENSE](LICENSE) for the warranty disclaimer. - ## Resources **Setup** @@ -85,7 +118,26 @@ and do not guarantee. ## Use it -**Copy the folder.** Your agent picks it up with no further setup. +**With [skills.sh](https://skills.sh)**, for Claude Code, Cursor, Codex and +the other agents it supports. It lists every skill here and asks which to +install and for which agents. + +```bash +npx skills add bruin-data/agent-resource-kit +npx skills add bruin-data/agent-resource-kit --skill ai-coding-spend # just one +npx skills add bruin-data/agent-resource-kit --list # look first +``` + +**As a Claude Code plugin.** Each group is a plugin: `bruin-agent`, +`startup-data-kit`, `data-engineering-skills`, `coding-agent-workflows` and +`tools`. Plugin skills are namespaced, such as `/startup-data-kit:ai-coding-spend`. + +```text +/plugin marketplace add bruin-data/agent-resource-kit +/plugin install startup-data-kit@bruin-agent-resource-kit +``` + +**Or copy the folder.** Your agent picks it up with no further setup. ```bash git clone https://github.com/bruin-data/agent-resource-kit @@ -108,6 +160,17 @@ I need to work out why our MRR stopped growing last quarter. It reads the index, then the one skill it needs. +## Tested + +> **TODO:** results pending. The comparison runs separately and fills in this +> table. + +| Question | Without skill | With skill | +|---|---|---| +| TODO | TODO | TODO | +| TODO | TODO | TODO | +| TODO | TODO | TODO | + ## Upstream documentation is the source of truth Every file here is a snapshot of how something worked the day it was written. @@ -158,10 +221,20 @@ has the shape, the labels, and what gets rejected. ``` No dependencies. It checks frontmatter, status labels, upstream notes and their -dates, index completeness, local links, and files that must never be committed. +dates, index and plugin manifest completeness, local links, sample data that +uses only reserved example domains, and files that must never be committed. CI runs it on every change, scans for credentials with gitleaks, and checks external links weekly so a dead upstream link surfaces on its own. +## Provided as-is + +> **Example code, provided as-is.** This repository is not part of the Bruin +> platform, not a supported Bruin product, and not covered by any support +> agreement or SLA. It is documentation and sample scripts: it stores no customer +> data, holds no credentials, and has no access to any production system. Scripts +> run on your own machine, under your own credentials, configured by you. See +> [LICENSE](LICENSE) for the warranty disclaimer. + ## Licence MIT. See [LICENSE](LICENSE). diff --git a/demo/ai-coding-spend.gif b/demo/ai-coding-spend.gif new file mode 100644 index 0000000..6ed6dc0 Binary files /dev/null and b/demo/ai-coding-spend.gif differ diff --git a/demo/ai-coding-spend.tape b/demo/ai-coding-spend.tape new file mode 100644 index 0000000..ac90a23 --- /dev/null +++ b/demo/ai-coding-spend.tape @@ -0,0 +1,51 @@ +# Try ai-coding-spend in 2 minutes: the ai-coding-usage template on fake data. +# +# Recorded with Bruin CLI v0.11.767 and VHS. Re-render from this folder: +# +# python3 ../resources/coding-agent-workflows/record-terminal-demo/scripts/render_demo.py ai-coding-spend.tape +# +# Hidden setup stands in for step 1's `git clone`: it links this working tree +# into a fresh folder as agent-resource-kit, so the recording shows the sample +# data at this commit rather than whatever is on GitHub. + +Output ai-coding-spend.gif + +Set Shell bash +Set FontSize 18 +Set Width 1280 +Set Height 760 +Set Margin 0 +Set Padding 28 +Set LineHeight 1.15 +Set TypingSpeed 25ms +Set Framerate 30 +Set CursorBlink false +Set Theme "GitHub Dark" + +Hide +Type "export KIT=$(git rev-parse --show-toplevel)" Enter +Type "rm -rf /tmp/try-ai-coding-spend && mkdir /tmp/try-ai-coding-spend && cd /tmp/try-ai-coding-spend" Enter +Type "ln -s $KIT agent-resource-kit" Enter +Type "unset NO_COLOR && export TERM=xterm-256color CLICOLOR=1" Enter +# \[ \] mark the colour codes as zero-width, so readline wraps the long query +# line correctly. +Type `export PS1="\n\[$(tput setaf 6)\]> \[$(tput sgr0)\]"` Enter +Type "clear" Enter +Show + +Type "# 1. The real ai-coding-usage template" Enter +Type "bruin init ai-coding-usage ai-coding-demo" Enter +Sleep 2s + +Type "# 2. Fake Claude Code and Cursor CSVs instead of the API assets" Enter +Type "cp agent-resource-kit/resources/startup-data-kit/ai-coding-spend/sample-data/*.{asset.yml,csv} bruin/ai-coding-demo/assets/raw/" Enter +Sleep 1s +Type "clear" Enter + +Type "# 3. Build every table on DuckDB, then query one" Enter +Type "cd bruin" Enter +Type "bruin run ai-coding-demo --full-refresh --workers 1 --start-date 2026-09-14 --end-date 2026-09-27" Enter +Sleep 4s +Type "clear" Enter +Type@15ms `bruin query -c duckdb-default -q "SELECT strftime(date_trunc('week', usage_date), '%Y-%m-%d') AS week, platform, CAST(SUM(total_tokens) AS BIGINT) AS tokens, ROUND(SUM(estimated_cost_usd), 2) AS est_cost_usd FROM marts.ai_coding_usage_by_user_day GROUP BY ALL ORDER BY ALL"` Enter +Sleep 6s diff --git a/resources/startup-data-kit/README.md b/resources/startup-data-kit/README.md index bc2f84c..c3759a7 100644 --- a/resources/startup-data-kit/README.md +++ b/resources/startup-data-kit/README.md @@ -25,7 +25,7 @@ domain reconciling against its source before adding a second. ## How each skill works -Every folder holds exactly these three files: +Every folder holds these three files: | File | What it is | |---|---| @@ -33,6 +33,10 @@ Every folder holds exactly these three files: | `workflow.md` | The shared setup process, from installing Bruin to reconciling the first run | | `analysis.md` | How to answer questions once the pipeline exists | +`ai-coding-spend` also carries a [`sample-data/`](ai-coding-spend/sample-data/) +folder: fake Claude Code and Cursor usage that runs its template on DuckDB with +no credentials. + `workflow.md` is identical in every folder, so a skill copied alone still works. `tests/check.py` fails if the copies drift; edit one and copy it to the rest. diff --git a/resources/startup-data-kit/ai-coding-spend/SKILL.md b/resources/startup-data-kit/ai-coding-spend/SKILL.md index 620eed8..26a3a95 100644 --- a/resources/startup-data-kit/ai-coding-spend/SKILL.md +++ b/resources/startup-data-kit/ai-coding-spend/SKILL.md @@ -10,7 +10,7 @@ description: Use when a startup wants AI coding tool usage and spend set up or a > **Upstream documentation wins.** Where this file disagrees with the [Bruin > docs](https://getbruin.com/docs/bruin/overview.html), `bruin --help`, or > Anthropic's or Cursor's API documentation, those are right and this file is -> stale. Written against Bruin CLI `v0.11.766`, checked 2026-10-01. +> stale. Written against Bruin CLI `v0.11.767`, checked 2026-10-02. Sets up a Claude Code and Cursor usage pipeline and answers adoption and cost questions from it. It exists to prevent an estimated cost being read as the @@ -20,6 +20,10 @@ bill, and usage data being turned into a ranking of engineers. Follow [workflow.md](workflow.md). +**No credentials yet?** [sample-data/](sample-data/README.md) runs the template +on fake usage in DuckDB. Use it to show the user what they will get; never +present its numbers as theirs. + > **Important: do not ask a fixed list of questions.** Read the template as it > is today and work out which of its choices this user needs to confirm. > Templates change, so the questions change with them. @@ -33,6 +37,7 @@ theirs to build. - Coverage is Claude Code on the first-party Anthropic API, and Cursor; Bedrock, Vertex AI, Foundry, Claude Platform on AWS, Claude Enterprise claude.ai users and every other tool are silently missing. - Cost columns are estimates, not the bill, built differently per vendor, with no seat fees; no seat list is ingested. - History lives only in the marts; `--full-refresh` drops it. +- A first run fails on the per-day marts until they exist; Bruin's materialization docs say to create them with `--full-refresh`, the template README does not. Ask first, and only while there is no history. **Usually needs the user's input:** diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/README.md b/resources/startup-data-kit/ai-coding-spend/sample-data/README.md new file mode 100644 index 0000000..5d019a2 --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/README.md @@ -0,0 +1,77 @@ +# Sample data for ai-coding-spend + +> **Upstream documentation wins.** Where this file disagrees with the +> [`ai-coding-usage` template README](https://getbruin.com/docs/bruin/getting-started/templates-docs/ai-coding-usage-README.html), +> the [seed asset docs](https://getbruin.com/docs/bruin/assets/seed.html) or +> `bruin run --help`, those are right and this file is stale. Written against +> Bruin CLI `v0.11.767`, checked 2026-10-02. + +**Every value here is invented.** Seven fictional people on `example.com`, one +CI key, two fictional weeks (2026-09-14 to 2026-09-27), made-up model names +and made-up per-token rates. Nothing is taken from real usage or real pricing. +[`generate.py`](generate.py) rebuilds the CSVs from a fixed seed. + +It runs the real `ai-coding-usage` template with no Anthropic or Cursor key and +no warehouse: three seed assets take the place of the three API ingestion +assets, and everything downstream is the template, unchanged. + +| File | Replaces | Shape | +|---|---|---| +| `claude_code_usage.asset.yml` + `.csv` | `raw.claude_code_usage` | One row per actor, day and terminal | +| `cursor_daily_usage.asset.yml` + `.csv` | `raw.cursor_daily_usage` | One row per person and day, active or not | +| `cursor_usage_events.asset.yml` + `.csv` | `raw.cursor_usage_events` | One row per request, `tokenUsage` as JSON | + +## Try it in 2 minutes + +Needs the [Bruin CLI](https://getbruin.com/docs/bruin/getting-started/introduction/installation.html) +and git. Run it in an empty folder that is not inside a git repository. + +```bash +# 1. Get the template and the sample data +git clone --depth 1 https://github.com/bruin-data/agent-resource-kit +bruin init ai-coding-usage ai-coding-demo + +# 2. Swap the Anthropic and Cursor API assets for the fake CSVs +cp agent-resource-kit/resources/startup-data-kit/ai-coding-spend/sample-data/*.{asset.yml,csv} \ + bruin/ai-coding-demo/assets/raw/ + +# 3. Build every table on DuckDB, then query one +cd bruin +bruin run ai-coding-demo --full-refresh --workers 1 --start-date 2026-09-14 --end-date 2026-09-27 +bruin query -c duckdb-default -q "SELECT strftime(date_trunc('week', usage_date), '%Y-%m-%d') AS week, platform, CAST(SUM(total_tokens) AS BIGINT) AS tokens, ROUND(SUM(estimated_cost_usd), 2) AS est_cost_usd FROM marts.ai_coding_usage_by_user_day GROUP BY ALL ORDER BY ALL" +``` + +Then install the skill and ask your agent something the data can answer, such +as "why did estimated Claude Code cost rise in the second week?" There is a +real answer in there, and two traps. + +Why the flags: + +- `--full-refresh`: the template's per-day marts use the `time_interval` + strategy, which needs the table to exist, and Bruin's + [materialization docs](https://getbruin.com/docs/bruin/assets/materialization.html) + say to create it on the first run this way. It drops and rebuilds every table + in the pipeline. That is harmless on this new demo database and destroys + history on a real one, so never carry it into a real pipeline's later runs. +- `--workers 1`: with the default workers, two of five test runs failed on the + DuckDB file lock, when a seed load and another asset or check opened the file + at the same moment. +- The dates: by default `bruin run` covers yesterday, which has no sample rows. + +Outside a git repository `bruin init` creates a `bruin/` project folder holding +`.bruin.yml` and the pipeline; inside one it puts the pipeline at the +repository root instead, so adjust the paths. The template still adds Anthropic +and Cursor connections to `.bruin.yml` as `${...}` references; with the API +assets swapped out, nothing reads them. + +## Unverified + +- **`schema_naming: direct`** on the two Cursor seed assets keeps the camelCase + column names the template's staging SQL expects. Without it the seed loader + converted them to snake_case and staging failed. The parameter is not in the + seed asset docs; it was observed working on `v0.11.767`. If staging fails on + a column such as `isActive`, check `bruin run --help` and the seed docs for + the current option. +- **The first-run failure** without `--full-refresh` was observed on + `v0.11.767`. The template's own README shows a plain `bruin run .`. Run + without the flag first on a newer CLI to see whether it is still needed. diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.asset.yml b/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.asset.yml new file mode 100644 index 0000000..da849c6 --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.asset.yml @@ -0,0 +1,70 @@ +name: raw.claude_code_usage +type: duckdb.seed + +description: Fake sample Claude Code usage, loaded from claude_code_usage.csv in place of the Anthropic Admin API. Every value is invented. + +columns: + - name: date + type: string + description: UTC date covered by the usage record. + primary_key: true + checks: + - name: not_null + - name: actor_type + type: string + description: Whether the actor is a user or an API key. + primary_key: true + checks: + - name: not_null + - name: actor_id + type: string + description: User email address or API key name. + primary_key: true + checks: + - name: not_null + - name: organization_id + type: string + description: Anthropic organization identifier. + - name: customer_type + type: string + description: Anthropic customer type, such as api or subscription. + - name: terminal_type + type: string + description: Terminal or environment where Claude Code was used. + primary_key: true + - name: num_sessions + type: integer + description: Number of distinct Claude Code sessions. + - name: lines_added + type: integer + description: Lines of code added with Claude Code. + - name: lines_removed + type: integer + description: Lines of code removed with Claude Code. + - name: commits_by_claude_code + type: integer + description: Git commits created through Claude Code. + - name: pull_requests_by_claude_code + type: integer + description: Pull requests created through Claude Code. + - name: total_input_tokens + type: integer + description: Input tokens used across all models. + - name: total_output_tokens + type: integer + description: Output tokens used across all models. + - name: total_cache_read_tokens + type: integer + description: Prompt cache read tokens used across all models. + - name: total_cache_creation_tokens + type: integer + description: Prompt cache creation tokens used across all models. + - name: total_estimated_cost_cents + type: numeric + description: Estimated cost in minor USD units (cents). + - name: models_used + type: string + description: Comma-separated Claude model names used by the actor. + +parameters: + path: claude_code_usage.csv diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.csv b/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.csv new file mode 100644 index 0000000..584cbbc --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/claude_code_usage.csv @@ -0,0 +1,79 @@ +date,actor_type,actor_id,organization_id,customer_type,terminal_type,num_sessions,lines_added,lines_removed,commits_by_claude_code,pull_requests_by_claude_code,total_input_tokens,total_output_tokens,total_cache_read_tokens,total_cache_creation_tokens,total_estimated_cost_cents,models_used +2026-09-14,user_actor,alex@example.com,org_example_demo,subscription,vscode,3,407,111,1,0,57703,16623,296957,28221,20.579,claude-haiku-demo +2026-09-14,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,3,646,217,3,0,72880,14626,401721,29055,22.2501,claude-haiku-demo +2026-09-14,user_actor,blair@example.com,org_example_demo,subscription,vscode,4,633,213,1,0,49789,9730,366451,29423,51.5589,claude-sonnet-demo +2026-09-14,user_actor,devon@example.com,org_example_demo,subscription,vscode,3,105,29,2,1,94873,23283,700383,53664,104.5219,claude-sonnet-demo +2026-09-14,user_actor,emery@example.com,org_example_demo,subscription,vscode,2,69,20,2,1,12245,3016,66744,6841,12.7652,claude-sonnet-demo +2026-09-14,user_actor,emery@example.com,org_example_demo,subscription,iTerm.app,4,105,31,0,0,21917,6450,119101,14986,25.4429,claude-sonnet-demo +2026-09-14,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,3,405,184,0,0,53180,13676,295068,31555,57.1532,claude-sonnet-demo +2026-09-14,api_actor,ci-review-bot,org_example_demo,api,non-interactive,21,0,0,0,0,57337,18736,311110,31497,22.1499,claude-haiku-demo +2026-09-15,user_actor,alex@example.com,org_example_demo,subscription,vscode,3,735,206,3,0,92062,25851,525513,70042,108.4262,claude-sonnet-demo +2026-09-15,user_actor,blair@example.com,org_example_demo,subscription,vscode,3,682,245,3,0,58827,10610,307122,36428,56.4373,claude-sonnet-demo +2026-09-15,user_actor,devon@example.com,org_example_demo,subscription,vscode,3,172,79,3,0,67077,15773,436552,42042,72.6449,claude-sonnet-demo +2026-09-15,user_actor,emery@example.com,org_example_demo,subscription,vscode,3,204,83,1,0,34179,7048,305893,18017,36.7589,claude-sonnet-demo +2026-09-15,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,2,373,172,2,0,55235,15261,335505,33262,62.0004,claude-sonnet-demo +2026-09-15,api_actor,ci-review-bot,org_example_demo,api,non-interactive,22,0,0,0,0,38858,6067,190306,23539,11.7647,claude-haiku-demo +2026-09-16,user_actor,alex@example.com,org_example_demo,subscription,vscode,3,288,160,1,0,48900,16028,406573,37730,65.0579,claude-sonnet-demo +2026-09-16,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,1,526,180,1,0,87749,30414,373162,35063,96.2892,claude-sonnet-demo +2026-09-16,user_actor,blair@example.com,org_example_demo,subscription,vscode,5,393,102,0,0,114775,35838,1020649,46188,136.1295,claude-sonnet-demo +2026-09-16,user_actor,devon@example.com,org_example_demo,subscription,vscode,5,200,77,0,0,35165,11743,210409,12479,39.1559,claude-sonnet-demo +2026-09-16,user_actor,devon@example.com,org_example_demo,subscription,iTerm.app,4,245,96,0,1,45714,12211,332023,32457,54.1628,claude-sonnet-demo +2026-09-16,user_actor,emery@example.com,org_example_demo,subscription,vscode,2,120,66,1,1,35459,11386,201532,16980,40.1302,claude-sonnet-demo +2026-09-16,api_actor,ci-review-bot,org_example_demo,api,non-interactive,21,0,0,0,0,36200,9852,153454,20728,12.6715,claude-haiku-demo +2026-09-17,user_actor,alex@example.com,org_example_demo,subscription,vscode,5,235,84,3,1,88553,20878,518440,42565,89.398,claude-sonnet-demo +2026-09-17,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,5,702,241,0,1,93926,32036,548889,64398,116.8477,claude-sonnet-demo +2026-09-17,user_actor,blair@example.com,org_example_demo,subscription,vscode,3,300,92,1,1,62177,10972,538817,24085,60.3075,claude-sonnet-demo +2026-09-17,user_actor,blair@example.com,org_example_demo,subscription,iTerm.app,4,328,132,3,1,29356,9131,137986,9640,30.2579,claude-sonnet-demo +2026-09-17,user_actor,devon@example.com,org_example_demo,subscription,vscode,2,273,81,2,1,45123,11192,277832,29729,16.6027,claude-haiku-demo +2026-09-17,user_actor,emery@example.com,org_example_demo,subscription,vscode,2,82,34,0,0,22133,6680,128954,15658,26.4003,claude-sonnet-demo +2026-09-17,user_actor,emery@example.com,org_example_demo,subscription,iTerm.app,2,40,16,3,1,13040,3498,90966,9390,15.4092,claude-sonnet-demo +2026-09-17,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,2,123,46,2,0,61676,20407,452606,33401,75.2169,claude-sonnet-demo +2026-09-17,api_actor,ci-review-bot,org_example_demo,api,non-interactive,25,0,0,0,0,55462,15759,336310,26650,20.12,claude-haiku-demo +2026-09-18,user_actor,alex@example.com,org_example_demo,subscription,vscode,3,506,274,0,0,169296,28192,1428750,51742,155.3425,claude-sonnet-demo +2026-09-18,user_actor,devon@example.com,org_example_demo,subscription,vscode,2,68,22,1,0,27088,6643,228578,17932,31.6727,claude-sonnet-demo +2026-09-18,user_actor,devon@example.com,org_example_demo,subscription,iTerm.app,5,79,28,0,1,24417,4711,179243,15863,25.7175,claude-sonnet-demo +2026-09-18,user_actor,emery@example.com,org_example_demo,subscription,vscode,1,128,39,3,1,33791,8434,177847,16859,34.4458,claude-sonnet-demo +2026-09-18,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,5,132,63,1,0,59678,11053,393278,43804,62.7077,claude-sonnet-demo +2026-09-18,api_actor,ci-review-bot,org_example_demo,api,non-interactive,12,0,0,0,0,21525,6615,91234,15757,8.342,claude-haiku-demo +2026-09-19,user_actor,emery@example.com,org_example_demo,subscription,vscode,3,46,25,1,1,5739,1532,44757,1836,2.017,claude-haiku-demo +2026-09-19,user_actor,emery@example.com,org_example_demo,subscription,iTerm.app,3,33,10,0,0,3910,1214,34878,2633,1.6759,claude-haiku-demo +2026-09-19,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,4,253,117,3,1,18913,3801,121798,8667,18.2795,claude-sonnet-demo +2026-09-21,user_actor,alex@example.com,org_example_demo,subscription,vscode,4,959,257,3,1,176837,39092,901623,118886,183.32,claude-sonnet-demo +2026-09-21,user_actor,blair@example.com,org_example_demo,subscription,vscode,2,168,54,0,1,28286,8284,129916,17735,10.4866,claude-haiku-demo +2026-09-21,user_actor,blair@example.com,org_example_demo,subscription,iTerm.app,3,389,233,1,1,59120,11388,448732,29870,19.8271,claude-haiku-demo +2026-09-21,user_actor,emery@example.com,org_example_demo,subscription,vscode,5,139,80,2,1,18630,6381,80362,8840,20.8864,claude-sonnet-demo +2026-09-21,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,4,288,117,0,0,50770,9612,228944,31981,48.5102,claude-sonnet-demo +2026-09-21,user_actor,sam.rivera@example.com,org_example_demo,subscription,iTerm.app,4,157,58,2,1,37329,8828,279521,22741,41.3542,claude-sonnet-demo +2026-09-21,api_actor,ci-review-bot,org_example_demo,api,non-interactive,29,0,0,0,0,44778,9953,213512,21396,14.2639,claude-haiku-demo +2026-09-22,user_actor,alex@example.com,org_example_demo,subscription,vscode,2,928,249,1,0,50395,11235,212116,23318,47.0787,claude-sonnet-demo +2026-09-22,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,2,646,369,3,0,32016,7808,288095,23309,38.7005,claude-sonnet-demo +2026-09-22,user_actor,blair@example.com,org_example_demo,subscription,vscode,2,223,54,3,0,49630,16582,434592,23336,61.5508,claude-sonnet-demo +2026-09-22,user_actor,blair@example.com,org_example_demo,subscription,iTerm.app,1,215,47,1,1,60287,14011,407661,42152,67.1394,claude-sonnet-demo +2026-09-22,user_actor,devon@example.com,org_example_demo,subscription,vscode,4,166,58,2,1,25415,3945,225540,18571,136.3616,"claude-opus-demo,claude-sonnet-demo" +2026-09-22,user_actor,devon@example.com,org_example_demo,subscription,iTerm.app,4,122,37,0,0,16489,3729,98425,11687,89.3779,"claude-opus-demo,claude-sonnet-demo" +2026-09-22,user_actor,emery@example.com,org_example_demo,subscription,vscode,1,183,38,0,0,39033,7682,277180,30496,42.9843,claude-sonnet-demo +2026-09-22,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,3,186,107,2,0,52616,16362,215121,23946,55.7612,claude-sonnet-demo +2026-09-22,api_actor,ci-review-bot,org_example_demo,api,non-interactive,16,0,0,0,0,31439,6042,154044,22818,10.5576,claude-haiku-demo +2026-09-23,user_actor,alex@example.com,org_example_demo,subscription,vscode,5,596,349,0,0,167235,50279,854496,76452,179.8934,claude-sonnet-demo +2026-09-23,user_actor,blair@example.com,org_example_demo,subscription,vscode,5,189,56,0,1,88737,17994,583692,34764,84.1594,claude-sonnet-demo +2026-09-23,user_actor,emery@example.com,org_example_demo,subscription,vscode,5,55,14,0,0,40794,6221,330699,27230,13.9006,claude-haiku-demo +2026-09-23,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,4,448,260,2,1,61228,19431,525445,37417,77.3096,claude-sonnet-demo +2026-09-23,api_actor,ci-review-bot,org_example_demo,api,non-interactive,29,0,0,0,0,51607,17830,371750,27347,21.2116,claude-haiku-demo +2026-09-24,user_actor,alex@example.com,org_example_demo,subscription,vscode,5,446,139,1,1,52757,12661,450159,38128,20.8738,claude-haiku-demo +2026-09-24,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,5,619,295,1,0,42530,6578,347109,28247,14.544,claude-haiku-demo +2026-09-24,user_actor,blair@example.com,org_example_demo,subscription,vscode,5,645,295,0,0,76176,24680,447611,34845,86.368,claude-sonnet-demo +2026-09-24,user_actor,devon@example.com,org_example_demo,subscription,vscode,2,408,108,2,1,25756,5983,114654,17282,133.1084,"claude-opus-demo,claude-sonnet-demo" +2026-09-24,user_actor,devon@example.com,org_example_demo,subscription,iTerm.app,1,128,50,2,0,18714,2958,167592,5888,86.4348,"claude-opus-demo,claude-sonnet-demo" +2026-09-24,user_actor,emery@example.com,org_example_demo,subscription,vscode,3,221,124,0,1,39293,11719,270807,29974,48.7309,claude-sonnet-demo +2026-09-24,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,1,456,229,2,1,31630,7371,226904,17150,33.7839,claude-sonnet-demo +2026-09-24,user_actor,sam.rivera@example.com,org_example_demo,subscription,iTerm.app,3,522,175,3,1,64817,12160,470695,39481,66.6113,claude-sonnet-demo +2026-09-24,api_actor,ci-review-bot,org_example_demo,api,non-interactive,20,0,0,0,0,21373,3416,162086,13018,7.0934,claude-haiku-demo +2026-09-25,user_actor,alex@example.com,org_example_demo,subscription,vscode,3,524,200,1,1,35266,7179,210982,15522,33.4985,claude-sonnet-demo +2026-09-25,user_actor,alex@example.com,org_example_demo,subscription,iTerm.app,3,541,295,1,0,70972,23534,396129,25011,77.8556,claude-sonnet-demo +2026-09-25,user_actor,blair@example.com,org_example_demo,subscription,vscode,2,201,52,1,0,105289,32868,879567,59109,129.4416,claude-sonnet-demo +2026-09-25,user_actor,devon@example.com,org_example_demo,subscription,vscode,1,457,147,1,0,72760,15447,396298,45059,368.9228,"claude-opus-demo,claude-sonnet-demo" +2026-09-25,user_actor,emery@example.com,org_example_demo,subscription,vscode,5,65,34,2,0,45161,9913,248055,30483,15.7635,claude-haiku-demo +2026-09-25,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,2,224,125,0,0,125336,33378,736858,95821,145.7064,claude-sonnet-demo +2026-09-25,api_actor,ci-review-bot,org_example_demo,api,non-interactive,29,0,0,0,0,32906,5428,204799,21590,10.7513,claude-haiku-demo +2026-09-26,user_actor,alex@example.com,org_example_demo,subscription,vscode,4,244,131,1,0,65579,16148,266457,22573,60.3543,claude-sonnet-demo +2026-09-26,user_actor,sam.rivera@example.com,org_example_demo,subscription,vscode,3,154,41,3,0,51161,12463,337786,24900,53.5139,claude-sonnet-demo diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.asset.yml b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.asset.yml new file mode 100644 index 0000000..4fcfeae --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.asset.yml @@ -0,0 +1,89 @@ +name: raw.cursor_daily_usage +type: duckdb.seed + +description: Fake sample Cursor daily usage, loaded from cursor_daily_usage.csv in place of the Cursor Admin API. Every value is invented. + +columns: + - name: date + type: bigint + description: UTC usage date as Unix epoch milliseconds. + primary_key: true + checks: + - name: not_null + - name: email + type: string + description: Cursor team member email address. + primary_key: true + checks: + - name: not_null + - name: isActive + type: boolean + description: Whether the user was active on this date. + - name: totalLinesAdded + type: bigint + description: Total lines added by the user. + - name: totalLinesDeleted + type: bigint + description: Total lines deleted by the user. + - name: acceptedLinesAdded + type: bigint + description: Lines added from accepted AI suggestions. + - name: acceptedLinesDeleted + type: bigint + description: Lines deleted from accepted AI suggestions. + - name: totalApplies + type: bigint + description: AI code apply operations. + - name: totalAccepts + type: bigint + description: Accepted AI suggestions. + - name: totalRejects + type: bigint + description: Rejected AI suggestions. + - name: totalTabsShown + type: bigint + description: Tab completions shown. + - name: totalTabsAccepted + type: bigint + description: Tab completions accepted. + - name: composerRequests + type: bigint + description: Composer or edit requests. + - name: chatRequests + type: bigint + description: Ask or chat requests. + - name: agentRequests + type: bigint + description: Agent requests. + - name: cmdkUsages + type: bigint + description: Command palette usages. + - name: subscriptionIncludedReqs + type: bigint + description: Requests included in the subscription. + - name: apiKeyReqs + type: bigint + description: Requests made with API keys. + - name: usageBasedReqs + type: bigint + description: Usage-based billing requests. + - name: bugbotUsages + type: bigint + description: Bugbot usages. + - name: mostUsedModel + type: string + description: Most frequently used model. + - name: applyMostUsedExtension + type: string + description: Most-used file extension for AI applies. + - name: tabMostUsedExtension + type: string + description: Most-used file extension for tab completions. + - name: clientVersion + type: string + description: Cursor client version. + +parameters: + path: cursor_daily_usage.csv + # Keep the camelCase column names the template staging SQL expects. + schema_naming: direct diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.csv b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.csv new file mode 100644 index 0000000..9e35551 --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_daily_usage.csv @@ -0,0 +1,71 @@ +date,email,isActive,totalLinesAdded,totalLinesDeleted,acceptedLinesAdded,acceptedLinesDeleted,totalApplies,totalAccepts,totalRejects,totalTabsShown,totalTabsAccepted,composerRequests,chatRequests,agentRequests,cmdkUsages,subscriptionIncludedReqs,apiKeyReqs,usageBasedReqs,bugbotUsages,mostUsedModel,applyMostUsedExtension,tabMostUsedExtension,clientVersion +1789344000000,alex@example.com,true,1168,467,700,233,25,24,1,280,117,10,8,4,4,22,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789344000000,casey@example.com,true,539,215,323,107,39,30,9,61,25,11,10,6,1,27,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789344000000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789344000000,finley@example.com,true,550,220,330,110,37,25,12,200,80,6,8,0,5,14,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789344000000,Sam.Rivera@Example.com,true,555,222,333,111,18,11,7,67,16,11,8,7,2,26,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789430400000,alex@example.com,true,493,197,295,98,43,34,9,172,67,7,7,7,6,21,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789430400000,casey@example.com,true,459,183,275,91,8,5,3,217,91,13,9,3,0,25,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789430400000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789430400000,finley@example.com,true,478,191,286,95,34,25,9,71,15,13,7,1,6,21,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789430400000,Sam.Rivera@Example.com,true,624,249,374,124,26,17,9,252,107,10,10,8,6,28,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789516800000,alex@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789516800000,casey@example.com,true,745,298,447,149,33,28,5,381,156,8,1,7,4,16,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789516800000,devon@example.com,true,372,148,223,74,40,32,8,210,84,9,10,12,3,31,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789516800000,finley@example.com,true,361,144,216,72,9,6,3,109,47,2,1,4,1,7,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789516800000,Sam.Rivera@Example.com,true,303,121,181,60,22,21,1,98,42,13,4,7,6,24,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789603200000,alex@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789603200000,casey@example.com,true,468,187,280,93,42,28,14,118,51,8,7,7,0,22,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789603200000,devon@example.com,true,238,95,142,47,32,24,8,274,76,4,10,7,3,21,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789603200000,finley@example.com,true,474,189,284,94,12,7,5,304,125,6,1,7,4,14,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789603200000,Sam.Rivera@Example.com,true,704,281,422,140,19,13,6,234,88,3,6,9,0,18,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789689600000,alex@example.com,true,866,346,519,173,11,6,5,255,111,15,2,8,1,25,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789689600000,casey@example.com,true,652,260,391,130,31,18,13,102,36,13,2,0,2,15,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789689600000,devon@example.com,true,209,83,125,41,19,16,3,294,61,12,2,6,5,20,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789689600000,finley@example.com,true,381,152,228,76,26,24,2,183,57,8,9,1,5,18,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789689600000,Sam.Rivera@Example.com,true,914,365,548,182,23,22,1,365,106,3,10,11,4,24,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789776000000,alex@example.com,true,201,80,120,40,40,38,2,349,94,9,6,7,3,22,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789776000000,casey@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789776000000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789776000000,finley@example.com,true,117,46,70,23,33,22,11,226,82,14,2,8,3,24,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789776000000,Sam.Rivera@Example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789862400000,alex@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789862400000,casey@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789862400000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789862400000,finley@example.com,true,189,75,113,37,23,10,13,218,95,12,1,9,3,22,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789862400000,Sam.Rivera@Example.com,true,160,64,96,32,25,12,13,66,17,4,6,10,0,20,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789948800000,alex@example.com,true,531,212,318,106,35,32,3,314,89,12,2,9,1,23,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1789948800000,casey@example.com,true,449,179,269,89,45,37,8,102,27,5,8,0,1,13,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789948800000,devon@example.com,true,125,50,75,25,45,37,8,154,46,13,2,7,0,22,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1789948800000,finley@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1789948800000,Sam.Rivera@Example.com,true,276,110,165,55,37,25,12,272,87,15,8,9,6,32,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790035200000,alex@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790035200000,casey@example.com,true,490,196,294,98,24,15,9,349,72,2,4,6,0,12,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790035200000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790035200000,finley@example.com,true,451,180,270,90,28,23,5,163,53,2,1,4,2,7,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790035200000,Sam.Rivera@Example.com,true,277,110,166,55,16,14,2,369,148,12,2,4,5,18,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790121600000,alex@example.com,true,1320,528,792,264,25,16,9,136,59,2,4,10,1,16,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790121600000,casey@example.com,true,451,180,270,90,35,25,10,222,58,11,3,4,4,18,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790121600000,devon@example.com,true,171,68,102,34,29,26,3,194,64,2,5,11,4,18,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790121600000,finley@example.com,true,578,231,346,115,20,18,2,235,90,10,7,3,3,20,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790121600000,Sam.Rivera@Example.com,true,809,323,485,161,31,25,6,353,76,15,3,0,3,18,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790208000000,alex@example.com,true,1268,507,760,253,34,28,6,123,40,8,9,4,5,21,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790208000000,casey@example.com,true,796,318,477,159,24,10,14,106,24,11,8,1,2,20,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790208000000,devon@example.com,true,134,53,80,26,20,15,5,338,133,10,7,8,4,25,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790208000000,finley@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790208000000,Sam.Rivera@Example.com,true,393,157,235,78,43,31,12,201,73,15,10,4,4,29,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790294400000,alex@example.com,true,556,222,333,111,27,17,10,341,75,2,4,2,1,8,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790294400000,casey@example.com,true,129,51,77,25,43,35,8,338,135,15,1,3,0,19,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790294400000,devon@example.com,true,180,72,108,36,28,16,12,113,46,2,3,8,6,13,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790294400000,finley@example.com,true,596,238,357,119,37,32,5,70,21,4,1,6,2,11,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790294400000,Sam.Rivera@Example.com,true,970,388,582,194,29,20,9,316,126,11,1,3,6,15,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790380800000,alex@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790380800000,casey@example.com,true,225,90,135,45,39,28,11,371,109,14,5,2,3,21,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790380800000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790380800000,finley@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790380800000,Sam.Rivera@Example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790467200000,alex@example.com,true,104,41,62,20,11,6,5,166,60,12,6,0,5,18,0,0,0,cursor-agent-demo,.ts,.py,9.9.0-demo +1790467200000,casey@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790467200000,devon@example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo +1790467200000,finley@example.com,true,241,96,144,48,25,18,7,144,62,8,2,8,0,18,0,0,0,cursor-fast-demo,.ts,.py,9.9.0-demo +1790467200000,Sam.Rivera@Example.com,false,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,9.9.0-demo diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.asset.yml b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.asset.yml new file mode 100644 index 0000000..dc1437a --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.asset.yml @@ -0,0 +1,44 @@ +name: raw.cursor_usage_events +type: duckdb.seed + +description: Fake sample Cursor usage events, loaded from cursor_usage_events.csv in place of the Cursor Admin API. Every value is invented. + +columns: + - name: timestamp + type: string + description: Event timestamp as epoch milliseconds or an ISO timestamp. + primary_key: true + checks: + - name: not_null + - name: userEmail + type: string + description: Email address of the user who made the request. + primary_key: true + checks: + - name: not_null + - name: model + type: string + description: Model used for the request. + - name: kind + type: string + description: Cursor usage or billing category. + - name: maxMode + type: boolean + description: Whether Cursor Max Mode was enabled. + - name: requestsCosts + type: numeric + description: Cursor request cost units. + - name: isTokenBasedCall + type: boolean + description: Whether token-level usage and cost are available. + - name: tokenUsage + type: string + description: Input, output, cache, and cost details for token-based calls. + - name: isFreeBugbot + type: boolean + description: Whether the event was a free Bugbot request. + +parameters: + path: cursor_usage_events.csv + # Keep the camelCase column names the template staging SQL expects. + schema_naming: direct diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.csv b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.csv new file mode 100644 index 0000000..676c419 --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/cursor_usage_events.csv @@ -0,0 +1,269 @@ +timestamp,userEmail,model,kind,maxMode,requestsCosts,isTokenBasedCall,tokenUsage,isFreeBugbot +1789411140000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":31542,""outputTokens"":8411,""cacheReadTokens"":155614,""cacheWriteTokens"":10129,""totalCents"":122.1836}",false +1789395420000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22563,""outputTokens"":5948,""cacheReadTokens"":97258,""cacheWriteTokens"":17479,""totalCents"":7.793}",false +1789415580000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22304,""outputTokens"":4889,""cacheReadTokens"":137155,""cacheWriteTokens"":16205,""totalCents"":7.5832}",false +1789396080000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":31654,""outputTokens"":10808,""cacheReadTokens"":210913,""cacheWriteTokens"":10846,""totalCents"":10.9535}",false +1789389660000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":38913,""outputTokens"":9727,""cacheReadTokens"":212798,""cacheWriteTokens"":23273,""totalCents"":165.5029}",false +1789381680000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":26734,""outputTokens"":6504,""cacheReadTokens"":132822,""cacheWriteTokens"":13357,""totalCents"":26.7697}",false +1789389180000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":27297,""outputTokens"":7370,""cacheReadTokens"":194535,""cacheWriteTokens"":18581,""totalCents"":128.1921}",false +1789384740000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":15180,""outputTokens"":3198,""cacheReadTokens"":93254,""cacheWriteTokens"":6988,""totalCents"":4.6032}",false +1789386960000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":16198,""outputTokens"":4810,""cacheReadTokens"":89406,""cacheWriteTokens"":6426,""totalCents"":68.6653}",false +1789397280000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":22855,""outputTokens"":7655,""cacheReadTokens"":179319,""cacheWriteTokens"":13980,""totalCents"":28.9611}",false +1789400640000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":17501,""outputTokens"":4984,""cacheReadTokens"":98854,""cacheWriteTokens"":10949,""totalCents"":6.1009}",false +1789403700000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18303,""outputTokens"":4747,""cacheReadTokens"":117297,""cacheWriteTokens"":10469,""totalCents"":80.2247}",false +1789411080000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19677,""outputTokens"":6448,""cacheReadTokens"":122539,""cacheWriteTokens"":8991,""totalCents"":22.6229}",false +1789407360000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15009,""outputTokens"":2888,""cacheReadTokens"":95835,""cacheWriteTokens"":5799,""totalCents"":55.5375}",false +1789390440000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":13263,""outputTokens"":2539,""cacheReadTokens"":54247,""cacheWriteTokens"":9672,""totalCents"":4.0934}",false +1789395600000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":20126,""outputTokens"":3843,""cacheReadTokens"":148944,""cacheWriteTokens"":7403,""totalCents"":19.0467}",false +1789396260000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19471,""outputTokens"":3630,""cacheReadTokens"":172166,""cacheWriteTokens"":10758,""totalCents"":6.4655}",false +1789380720000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10823,""outputTokens"":2054,""cacheReadTokens"":56518,""cacheWriteTokens"":6350,""totalCents"":41.6188}",false +1789405200000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":18659,""outputTokens"":3580,""cacheReadTokens"":103071,""cacheWriteTokens"":5937,""totalCents"":16.2862}",false +1789410540000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":22640,""outputTokens"":7605,""cacheReadTokens"":188884,""cacheWriteTokens"":7731,""totalCents"":107.0606}",false +1789415100000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18026,""outputTokens"":5598,""cacheReadTokens"":133860,""cacheWriteTokens"":13863,""totalCents"":92.0769}",false +1789494360000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":24603,""outputTokens"":4260,""cacheReadTokens"":161215,""cacheWriteTokens"":12951,""totalCents"":23.464}",false +1789468020000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":40723,""outputTokens"":14130,""cacheReadTokens"":353485,""cacheWriteTokens"":30607,""totalCents"":55.4941}",false +1789487400000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":17752,""outputTokens"":5887,""cacheReadTokens"":110292,""cacheWriteTokens"":13995,""totalCents"":6.9823}",false +1789467420000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":21207,""outputTokens"":4203,""cacheReadTokens"":110525,""cacheWriteTokens"":10691,""totalCents"":79.9659}",false +1789476480000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15218,""outputTokens"":4286,""cacheReadTokens"":71327,""cacheWriteTokens"":6553,""totalCents"":62.3663}",false +1789459380000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10294,""outputTokens"":2530,""cacheReadTokens"":77412,""cacheWriteTokens"":4834,""totalCents"":44.0732}",false +1789481400000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":27293,""outputTokens"":7604,""cacheReadTokens"":150289,""cacheWriteTokens"":17403,""totalCents"":9.4492}",false +1789478880000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":16201,""outputTokens"":3960,""cacheReadTokens"":74502,""cacheWriteTokens"":10074,""totalCents"":16.8131}",false +1789483020000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":23211,""outputTokens"":3605,""cacheReadTokens"":136908,""cacheWriteTokens"":10127,""totalCents"":81.1027}",false +1789497660000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19059,""outputTokens"":6045,""cacheReadTokens"":120138,""cacheWriteTokens"":9721,""totalCents"":6.7404}",false +1789475640000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":9331,""outputTokens"":2704,""cacheReadTokens"":38182,""cacheWriteTokens"":3844,""totalCents"":9.4423}",false +1789460460000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7611,""outputTokens"":2222,""cacheReadTokens"":40384,""cacheWriteTokens"":2745,""totalCents"":7.8572}",false +1789499760000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":8248,""outputTokens"":2487,""cacheReadTokens"":71347,""cacheWriteTokens"":2640,""totalCents"":2.8631}",false +1789460400000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":10745,""outputTokens"":2520,""cacheReadTokens"":81813,""cacheWriteTokens"":6037,""totalCents"":3.6553}",false +1789500600000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":16440,""outputTokens"":5498,""cacheReadTokens"":104895,""cacheWriteTokens"":12339,""totalCents"":6.4345}",false +1789480320000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":17736,""outputTokens"":5410,""cacheReadTokens"":159194,""cacheWriteTokens"":11063,""totalCents"":22.3602}",false +1789474380000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13704,""outputTokens"":2398,""cacheReadTokens"":62402,""cacheWriteTokens"":7983,""totalCents"":50.2955}",false +1789462920000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":29214,""outputTokens"":9485,""cacheReadTokens"":182389,""cacheWriteTokens"":16947,""totalCents"":34.8185}",false +1789500960000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17069,""outputTokens"":3341,""cacheReadTokens"":99376,""cacheWriteTokens"":11055,""totalCents"":69.0364}",false +1789483320000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":16081,""outputTokens"":5146,""cacheReadTokens"":108593,""cacheWriteTokens"":12845,""totalCents"":6.3581}",false +1789571940000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19571,""outputTokens"":5419,""cacheReadTokens"":81327,""cacheWriteTokens"":12657,""totalCents"":21.186}",false +1789568400000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":24049,""outputTokens"":5722,""cacheReadTokens"":128606,""cacheWriteTokens"":7939,""totalCents"":90.532}",false +1789563360000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":12012,""outputTokens"":3172,""cacheReadTokens"":62048,""cacheWriteTokens"":6580,""totalCents"":50.7622}",false +1789552320000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":9101,""outputTokens"":2442,""cacheReadTokens"":51093,""cacheWriteTokens"":3051,""totalCents"":2.7792}",false +1789547520000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":8162,""outputTokens"":1494,""cacheReadTokens"":70350,""cacheWriteTokens"":5179,""totalCents"":8.7422}",false +1789577520000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19226,""outputTokens"":6459,""cacheReadTokens"":163434,""cacheWriteTokens"":12839,""totalCents"":25.1739}",false +1789557120000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15813,""outputTokens"":2708,""cacheReadTokens"":110014,""cacheWriteTokens"":6421,""totalCents"":58.0568}",false +1789551600000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19164,""outputTokens"":6426,""cacheReadTokens"":127816,""cacheWriteTokens"":7686,""totalCents"":6.7257}",false +1789555140000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17263,""outputTokens"":3259,""cacheReadTokens"":132846,""cacheWriteTokens"":9614,""totalCents"":70.6321}",false +1789580520000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11755,""outputTokens"":4097,""cacheReadTokens"":97590,""cacheWriteTokens"":4945,""totalCents"":57.8163}",false +1789545960000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19147,""outputTokens"":5112,""cacheReadTokens"":126969,""cacheWriteTokens"":9511,""totalCents"":6.4181}",false +1789552860000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":7776,""outputTokens"":2697,""cacheReadTokens"":47369,""cacheWriteTokens"":3351,""totalCents"":36.224}",false +1789556040000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10567,""outputTokens"":1603,""cacheReadTokens"":87071,""cacheWriteTokens"":4541,""totalCents"":39.5584}",false +1789550160000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15229,""outputTokens"":3487,""cacheReadTokens"":98041,""cacheWriteTokens"":7325,""totalCents"":15.4873}",false +1789584000000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11526,""outputTokens"":2622,""cacheReadTokens"":91277,""cacheWriteTokens"":6004,""totalCents"":3.8647}",false +1789554180000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19585,""outputTokens"":6182,""cacheReadTokens"":94473,""cacheWriteTokens"":6334,""totalCents"":20.3579}",false +1789567020000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7032,""outputTokens"":2222,""cacheReadTokens"":55290,""cacheWriteTokens"":4860,""totalCents"":8.9238}",false +1789585740000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":18399,""outputTokens"":4575,""cacheReadTokens"":107486,""cacheWriteTokens"":5622,""totalCents"":17.715}",false +1789585620000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":11421,""outputTokens"":2486,""cacheReadTokens"":61823,""cacheWriteTokens"":5334,""totalCents"":11.0102}",false +1789588260000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":25020,""outputTokens"":6752,""cacheReadTokens"":202519,""cacheWriteTokens"":10348,""totalCents"":27.5901}",false +1789570560000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":24852,""outputTokens"":8616,""cacheReadTokens"":108837,""cacheWriteTokens"":9903,""totalCents"":8.2578}",false +1789568160000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":28869,""outputTokens"":7663,""cacheReadTokens"":163520,""cacheWriteTokens"":13811,""totalCents"":9.3137}",false +1789566540000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":27468,""outputTokens"":6905,""cacheReadTokens"":141279,""cacheWriteTokens"":11706,""totalCents"":8.3848}",false +1789658640000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":23109,""outputTokens"":3724,""cacheReadTokens"":103950,""cacheWriteTokens"":12706,""totalCents"":6.4283}",false +1789652340000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":18825,""outputTokens"":4566,""cacheReadTokens"":166614,""cacheWriteTokens"":13408,""totalCents"":7.051}",false +1789654860000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":21494,""outputTokens"":6271,""cacheReadTokens"":179099,""cacheWriteTokens"":9301,""totalCents"":7.6114}",false +1789640340000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":17095,""outputTokens"":5312,""cacheReadTokens"":143487,""cacheWriteTokens"":10479,""totalCents"":6.579}",false +1789642020000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15068,""outputTokens"":4780,""cacheReadTokens"":75719,""cacheWriteTokens"":4540,""totalCents"":62.6579}",false +1789644660000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":18068,""outputTokens"":3639,""cacheReadTokens"":141782,""cacheWriteTokens"":6525,""totalCents"":5.4958}",false +1789654200000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14352,""outputTokens"":2614,""cacheReadTokens"":126762,""cacheWriteTokens"":7740,""totalCents"":4.7159}",false +1789649880000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":17114,""outputTokens"":3558,""cacheReadTokens"":81469,""cacheWriteTokens"":10799,""totalCents"":16.9649}",false +1789667760000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13673,""outputTokens"":3742,""cacheReadTokens"":76601,""cacheWriteTokens"":7109,""totalCents"":58.7152}",false +1789665960000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":18236,""outputTokens"":5644,""cacheReadTokens"":109876,""cacheWriteTokens"":5860,""totalCents"":19.4306}",false +1789655460000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13622,""outputTokens"":3247,""cacheReadTokens"":73707,""cacheWriteTokens"":8347,""totalCents"":57.1937}",false +1789673820000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11895,""outputTokens"":2675,""cacheReadTokens"":102913,""cacheWriteTokens"":7555,""totalCents"":54.0061}",false +1789657020000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":10220,""outputTokens"":2115,""cacheReadTokens"":74221,""cacheWriteTokens"":8174,""totalCents"":11.5304}",false +1789654920000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":7772,""outputTokens"":2441,""cacheReadTokens"":50204,""cacheWriteTokens"":2647,""totalCents"":2.5865}",false +1789633380000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19439,""outputTokens"":5522,""cacheReadTokens"":122455,""cacheWriteTokens"":11264,""totalCents"":22.0124}",false +1789670400000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":12152,""outputTokens"":3145,""cacheReadTokens"":72160,""cacheWriteTokens"":7063,""totalCents"":13.1765}",false +1789650480000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":18388,""outputTokens"":3386,""cacheReadTokens"":137997,""cacheWriteTokens"":11172,""totalCents"":5.9697}",false +1789662360000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13526,""outputTokens"":2534,""cacheReadTokens"":63413,""cacheWriteTokens"":6269,""totalCents"":48.4483}",false +1789671360000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":18513,""outputTokens"":2785,""cacheReadTokens"":95860,""cacheWriteTokens"":10937,""totalCents"":5.291}",false +1789670820000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18022,""outputTokens"":2908,""cacheReadTokens"":132346,""cacheWriteTokens"":8419,""totalCents"":67.5844}",false +1789744800000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":32385,""outputTokens"":10410,""cacheReadTokens"":272276,""cacheWriteTokens"":16200,""totalCents"":158.2951}",false +1789749420000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":32967,""outputTokens"":8712,""cacheReadTokens"":217018,""cacheWriteTokens"":12200,""totalCents"":34.0436}",false +1789755360000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":16875,""outputTokens"":3479,""cacheReadTokens"":73974,""cacheWriteTokens"":12008,""totalCents"":17.0032}",false +1789753980000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":36395,""outputTokens"":10782,""cacheReadTokens"":170523,""cacheWriteTokens"":26801,""totalCents"":42.2576}",false +1789754940000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17197,""outputTokens"":5975,""cacheReadTokens"":71711,""cacheWriteTokens"":12359,""totalCents"":83.6302}",false +1789730700000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":34062,""outputTokens"":8583,""cacheReadTokens"":251271,""cacheWriteTokens"":22009,""totalCents"":155.5384}",false +1789755600000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11516,""outputTokens"":3081,""cacheReadTokens"":81066,""cacheWriteTokens"":8506,""totalCents"":4.2579}",false +1789752120000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":20458,""outputTokens"":6782,""cacheReadTokens"":158702,""cacheWriteTokens"":8624,""totalCents"":24.3055}",false +1789723020000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":28060,""outputTokens"":8498,""cacheReadTokens"":204411,""cacheWriteTokens"":16962,""totalCents"":134.6323}",false +1789747440000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":25115,""outputTokens"":4208,""cacheReadTokens"":224555,""cacheWriteTokens"":15013,""totalCents"":104.8521}",false +1789739280000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10800,""outputTokens"":2032,""cacheReadTokens"":55453,""cacheWriteTokens"":8341,""totalCents"":44.3179}",false +1789722420000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":9065,""outputTokens"":2395,""cacheReadTokens"":45289,""cacheWriteTokens"":6010,""totalCents"":3.0686}",false +1789750380000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18400,""outputTokens"":4431,""cacheReadTokens"":90384,""cacheWriteTokens"":9722,""totalCents"":74.0951}",false +1789723380000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19665,""outputTokens"":3864,""cacheReadTokens"":167729,""cacheWriteTokens"":14517,""totalCents"":22.1712}",false +1789751280000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19925,""outputTokens"":6369,""cacheReadTokens"":124948,""cacheWriteTokens"":6669,""totalCents"":21.7803}",false +1789718820000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":14953,""outputTokens"":4212,""cacheReadTokens"":113161,""cacheWriteTokens"":11480,""totalCents"":74.0149}",false +1789735440000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":10782,""outputTokens"":3502,""cacheReadTokens"":95575,""cacheWriteTokens"":5130,""totalCents"":13.2786}",false +1789754100000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11760,""outputTokens"":3800,""cacheReadTokens"":92857,""cacheWriteTokens"":6685,""totalCents"":4.4602}",false +1789746780000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":8729,""outputTokens"":2415,""cacheReadTokens"":50976,""cacheWriteTokens"":5683,""totalCents"":39.6064}",false +1789743300000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":31407,""outputTokens"":9849,""cacheReadTokens"":219867,""cacheWriteTokens"":21016,""totalCents"":11.906}",false +1789735680000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":12284,""outputTokens"":4232,""cacheReadTokens"":89117,""cacheWriteTokens"":9583,""totalCents"":16.3003}",false +1789734180000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22013,""outputTokens"":6538,""cacheReadTokens"":194862,""cacheWriteTokens"":14119,""totalCents"":8.53}",false +1789743660000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22006,""outputTokens"":4941,""cacheReadTokens"":129574,""cacheWriteTokens"":7249,""totalCents"":6.3789}",false +1789731060000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":23649,""outputTokens"":6686,""cacheReadTokens"":105678,""cacheWriteTokens"":17878,""totalCents"":8.3308}",false +1789824600000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":12383,""outputTokens"":3624,""cacheReadTokens"":103403,""cacheWriteTokens"":4380,""totalCents"":13.8955}",false +1789808700000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":9431,""outputTokens"":3227,""cacheReadTokens"":79270,""cacheWriteTokens"":7120,""totalCents"":12.7179}",false +1789831020000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":14950,""outputTokens"":3551,""cacheReadTokens"":82571,""cacheWriteTokens"":9773,""totalCents"":15.9535}",false +1789817400000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":18232,""outputTokens"":4320,""cacheReadTokens"":145614,""cacheWriteTokens"":6956,""totalCents"":18.9265}",false +1789838460000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":9904,""outputTokens"":2358,""cacheReadTokens"":50057,""cacheWriteTokens"":4808,""totalCents"":9.8129}",false +1789835220000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":3270,""outputTokens"":1140,""cacheReadTokens"":13936,""cacheWriteTokens"":1640,""totalCents"":3.7241}",false +1789840200000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7420,""outputTokens"":1516,""cacheReadTokens"":52283,""cacheWriteTokens"":5886,""totalCents"":8.2757}",false +1789820280000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":8229,""outputTokens"":1796,""cacheReadTokens"":34496,""cacheWriteTokens"":5949,""totalCents"":33.7138}",false +1789838340000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":3452,""outputTokens"":926,""cacheReadTokens"":25100,""cacheWriteTokens"":2261,""totalCents"":16.1019}",false +1789930860000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":4768,""outputTokens"":1252,""cacheReadTokens"":31868,""cacheWriteTokens"":1638,""totalCents"":4.8787}",false +1789922220000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":6448,""outputTokens"":1178,""cacheReadTokens"":37791,""cacheWriteTokens"":4834,""totalCents"":2.0982}",false +1789915020000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":6301,""outputTokens"":1372,""cacheReadTokens"":48782,""cacheWriteTokens"":1994,""totalCents"":1.916}",false +1789895220000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7086,""outputTokens"":1801,""cacheReadTokens"":61786,""cacheWriteTokens"":4101,""totalCents"":8.2188}",false +1789930140000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":6981,""outputTokens"":1959,""cacheReadTokens"":39913,""cacheWriteTokens"":4424,""totalCents"":7.8892}",false +1789921500000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":4591,""outputTokens"":1086,""cacheReadTokens"":41156,""cacheWriteTokens"":1671,""totalCents"":19.4704}",false +1789931580000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":6163,""outputTokens"":1049,""cacheReadTokens"":31993,""cacheWriteTokens"":3106,""totalCents"":5.5469}",false +1789912320000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7719,""outputTokens"":1929,""cacheReadTokens"":61829,""cacheWriteTokens"":5561,""totalCents"":9.1494}",false +1789927380000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11728,""outputTokens"":3690,""cacheReadTokens"":82382,""cacheWriteTokens"":5848,""totalCents"":54.8714}",false +1789896420000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10836,""outputTokens"":2152,""cacheReadTokens"":95927,""cacheWriteTokens"":6433,""totalCents"":47.0759}",false +1789904280000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":6077,""outputTokens"":1834,""cacheReadTokens"":35670,""cacheWriteTokens"":3482,""totalCents"":27.7998}",false +1789893360000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":9846,""outputTokens"":1678,""cacheReadTokens"":82522,""cacheWriteTokens"":6970,""totalCents"":42.2408}",false +1789916340000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":10152,""outputTokens"":2340,""cacheReadTokens"":70671,""cacheWriteTokens"":4146,""totalCents"":10.2305}",false +1789913820000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":6609,""outputTokens"":1931,""cacheReadTokens"":54874,""cacheWriteTokens"":2817,""totalCents"":30.3272}",false +1789902480000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13002,""outputTokens"":2625,""cacheReadTokens"":106516,""cacheWriteTokens"":5052,""totalCents"":12.9281}",false +1790006940000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":33127,""outputTokens"":6541,""cacheReadTokens"":159635,""cacheWriteTokens"":15477,""totalCents"":121.3701}",false +1790016480000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":32140,""outputTokens"":9790,""cacheReadTokens"":273072,""cacheWriteTokens"":11605,""totalCents"":36.871}",false +1790016660000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22720,""outputTokens"":5741,""cacheReadTokens"":196895,""cacheWriteTokens"":12563,""totalCents"":8.1077}",false +1789994940000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":34738,""outputTokens"":11248,""cacheReadTokens"":220668,""cacheWriteTokens"":21072,""totalCents"":12.8137}",false +1789978740000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":24157,""outputTokens"":4678,""cacheReadTokens"":130655,""cacheWriteTokens"":17331,""totalCents"":24.6829}",false +1789998540000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":45544,""outputTokens"":7417,""cacheReadTokens"":303485,""cacheWriteTokens"":18799,""totalCents"":40.9429}",false +1790008920000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":39959,""outputTokens"":7368,""cacheReadTokens"":309606,""cacheWriteTokens"":22904,""totalCents"":163.6675}",false +1789995840000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":27259,""outputTokens"":9285,""cacheReadTokens"":189033,""cacheWriteTokens"":10083,""totalCents"":126.2293}",false +1790002320000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":17385,""outputTokens"":5373,""cacheReadTokens"":144987,""cacheWriteTokens"":13272,""totalCents"":22.6016}",false +1790015940000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13941,""outputTokens"":2819,""cacheReadTokens"":72017,""cacheWriteTokens"":10124,""totalCents"":57.4712}",false +1789991100000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":26976,""outputTokens"":8928,""cacheReadTokens"":213508,""cacheWriteTokens"":13455,""totalCents"":131.7427}",false +1789994340000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":25203,""outputTokens"":5469,""cacheReadTokens"":135096,""cacheWriteTokens"":11356,""totalCents"":7.4784}",false +1789985100000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14050,""outputTokens"":4592,""cacheReadTokens"":103629,""cacheWriteTokens"":10237,""totalCents"":5.5577}",false +1789991760000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13811,""outputTokens"":4002,""cacheReadTokens"":96331,""cacheWriteTokens"":9083,""totalCents"":16.4424}",false +1789977600000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19048,""outputTokens"":3305,""cacheReadTokens"":112399,""cacheWriteTokens"":14655,""totalCents"":6.1827}",false +1790005260000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":21666,""outputTokens"":6303,""cacheReadTokens"":187046,""cacheWriteTokens"":8508,""totalCents"":24.7562}",false +1790020740000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15687,""outputTokens"":2982,""cacheReadTokens"":74478,""cacheWriteTokens"":12515,""totalCents"":16.1066}",false +1789987920000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":23576,""outputTokens"":4905,""cacheReadTokens"":196962,""cacheWriteTokens"":10938,""totalCents"":97.7636}",false +1790013180000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15079,""outputTokens"":4459,""cacheReadTokens"":81915,""cacheWriteTokens"":8121,""totalCents"":16.715}",false +1789995060000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":22660,""outputTokens"":4579,""cacheReadTokens"":150408,""cacheWriteTokens"":14589,""totalCents"":23.6496}",false +1789991640000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11415,""outputTokens"":2437,""cacheReadTokens"":91435,""cacheWriteTokens"":7936,""totalCents"":51.1962}",false +1789991820000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10707,""outputTokens"":3354,""cacheReadTokens"":66067,""cacheWriteTokens"":7537,""totalCents"":52.2059}",false +1790005920000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":20541,""outputTokens"":7043,""cacheReadTokens"":136263,""cacheWriteTokens"":14149,""totalCents"":26.1206}",false +1790016060000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":20851,""outputTokens"":6468,""cacheReadTokens"":127417,""cacheWriteTokens"":9981,""totalCents"":7.1941}",false +1790005380000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":30789,""outputTokens"":4697,""cacheReadTokens"":272583,""cacheWriteTokens"":14176,""totalCents"":119.1028}",false +1790011080000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":32702,""outputTokens"":10138,""cacheReadTokens"":209611,""cacheWriteTokens"":23835,""totalCents"":12.4009}",false +1790086320000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14742,""outputTokens"":4422,""cacheReadTokens"":85750,""cacheWriteTokens"":10214,""totalCents"":5.3773}",false +1790083380000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":15750,""outputTokens"":5294,""cacheReadTokens"":75118,""cacheWriteTokens"":10836,""totalCents"":5.7983}",false +1790103960000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":14667,""outputTokens"":3552,""cacheReadTokens"":82610,""cacheWriteTokens"":11440,""totalCents"":65.9856}",false +1790075700000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":23311,""outputTokens"":4624,""cacheReadTokens"":94959,""cacheWriteTokens"":15397,""totalCents"":90.2078}",false +1790098800000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":14086,""outputTokens"":3113,""cacheReadTokens"":61675,""cacheWriteTokens"":6569,""totalCents"":13.2089}",false +1790083500000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":23086,""outputTokens"":5129,""cacheReadTokens"":132148,""cacheWriteTokens"":11172,""totalCents"":91.093}",false +1790104380000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":19202,""outputTokens"":6069,""cacheReadTokens"":141101,""cacheWriteTokens"":12587,""totalCents"":95.269}",false +1790099220000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":10717,""outputTokens"":1950,""cacheReadTokens"":71233,""cacheWriteTokens"":7047,""totalCents"":10.9197}",false +1790102340000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11171,""outputTokens"":2921,""cacheReadTokens"":96398,""cacheWriteTokens"":8881,""totalCents"":55.8205}",false +1790094000000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":18071,""outputTokens"":4288,""cacheReadTokens"":115881,""cacheWriteTokens"":14232,""totalCents"":20.6667}",false +1790065680000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15469,""outputTokens"":4188,""cacheReadTokens"":107795,""cacheWriteTokens"":8233,""totalCents"":17.2439}",false +1790072760000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15546,""outputTokens"":2744,""cacheReadTokens"":67758,""cacheWriteTokens"":6785,""totalCents"":53.4277}",false +1790102520000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":17572,""outputTokens"":3262,""cacheReadTokens"":118521,""cacheWriteTokens"":6579,""totalCents"":5.0696}",false +1790100780000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7183,""outputTokens"":2075,""cacheReadTokens"":50753,""cacheWriteTokens"":5399,""totalCents"":8.8146}",false +1790079420000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11047,""outputTokens"":1931,""cacheReadTokens"":64930,""cacheWriteTokens"":8713,""totalCents"":3.6155}",false +1790102040000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13797,""outputTokens"":3996,""cacheReadTokens"":75157,""cacheWriteTokens"":6182,""totalCents"":58.8242}",false +1790075160000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":19309,""outputTokens"":6580,""cacheReadTokens"":159688,""cacheWriteTokens"":12136,""totalCents"":7.6768}",false +1790070300000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":13122,""outputTokens"":2279,""cacheReadTokens"":60402,""cacheWriteTokens"":5533,""totalCents"":44.9681}",false +1790085600000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":25150,""outputTokens"":7883,""cacheReadTokens"":119084,""cacheWriteTokens"":18932,""totalCents"":30.0415}",false +1790099160000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":21954,""outputTokens"":6448,""cacheReadTokens"":189359,""cacheWriteTokens"":12911,""totalCents"":26.7806}",false +1790080200000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":27043,""outputTokens"":4374,""cacheReadTokens"":231547,""cacheWriteTokens"":17895,""totalCents"":28.3309}",false +1790193480000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":31544,""outputTokens"":8538,""cacheReadTokens"":165691,""cacheWriteTokens"":15894,""totalCents"":10.2133}",false +1790190960000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":38801,""outputTokens"":6049,""cacheReadTokens"":231567,""cacheWriteTokens"":23572,""totalCents"":11.5619}",false +1790155920000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":30837,""outputTokens"":10761,""cacheReadTokens"":185623,""cacheWriteTokens"":9781,""totalCents"":138.5167}",false +1790186580000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":30286,""outputTokens"":5925,""cacheReadTokens"":173611,""cacheWriteTokens"":12357,""totalCents"":27.8155}",false +1790184840000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":42971,""outputTokens"":8419,""cacheReadTokens"":279127,""cacheWriteTokens"":13509,""totalCents"":155.8379}",false +1790189280000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":29370,""outputTokens"":9766,""cacheReadTokens"":157142,""cacheWriteTokens"":14944,""totalCents"":135.113}",false +1790167440000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":27099,""outputTokens"":7986,""cacheReadTokens"":234381,""cacheWriteTokens"":20527,""totalCents"":10.814}",false +1790172480000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":24244,""outputTokens"":7061,""cacheReadTokens"":206160,""cacheWriteTokens"":12791,""totalCents"":8.9093}",false +1790159760000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":27074,""outputTokens"":7550,""cacheReadTokens"":136157,""cacheWriteTokens"":17298,""totalCents"":30.0187}",false +1790159280000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":29179,""outputTokens"":9261,""cacheReadTokens"":236176,""cacheWriteTokens"":10376,""totalCents"":10.2811}",false +1790186640000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":26199,""outputTokens"":5830,""cacheReadTokens"":167261,""cacheWriteTokens"":19246,""totalCents"":9.0303}",false +1790181660000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10830,""outputTokens"":2692,""cacheReadTokens"":51606,""cacheWriteTokens"":5556,""totalCents"":43.6747}",false +1790172960000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":20974,""outputTokens"":6092,""cacheReadTokens"":109297,""cacheWriteTokens"":6667,""totalCents"":84.8369}",false +1790182020000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17356,""outputTokens"":3616,""cacheReadTokens"":85315,""cacheWriteTokens"":9042,""totalCents"":66.324}",false +1790165520000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15201,""outputTokens"":3832,""cacheReadTokens"":117759,""cacheWriteTokens"":7820,""totalCents"":67.0943}",false +1790166900000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":14053,""outputTokens"":2489,""cacheReadTokens"":76098,""cacheWriteTokens"":6686,""totalCents"":50.9584}",false +1790166840000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13919,""outputTokens"":2982,""cacheReadTokens"":76801,""cacheWriteTokens"":9628,""totalCents"":14.5632}",false +1790168640000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15011,""outputTokens"":2965,""cacheReadTokens"":80703,""cacheWriteTokens"":9264,""totalCents"":14.8459}",false +1790162400000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":8102,""outputTokens"":1688,""cacheReadTokens"":42373,""cacheWriteTokens"":4173,""totalCents"":2.4308}",false +1790190780000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":12032,""outputTokens"":3892,""cacheReadTokens"":73060,""cacheWriteTokens"":5783,""totalCents"":4.2135}",false +1790177940000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":20284,""outputTokens"":4492,""cacheReadTokens"":89332,""cacheWriteTokens"":15258,""totalCents"":6.6258}",false +1790180940000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":23537,""outputTokens"":7434,""cacheReadTokens"":104289,""cacheWriteTokens"":15725,""totalCents"":27.2376}",false +1790190180000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":21638,""outputTokens"":5555,""cacheReadTokens"":100899,""cacheWriteTokens"":7469,""totalCents"":6.3284}",false +1790170380000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":15774,""outputTokens"":2379,""cacheReadTokens"":69399,""cacheWriteTokens"":9887,""totalCents"":14.0903}",false +1790268600000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":47232,""outputTokens"":11786,""cacheReadTokens"":405769,""cacheWriteTokens"":28474,""totalCents"":17.0545}",false +1790241600000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17002,""outputTokens"":5922,""cacheReadTokens"":141689,""cacheWriteTokens"":9640,""totalCents"":87.3971}",false +1790246340000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":36448,""outputTokens"":8016,""cacheReadTokens"":171136,""cacheWriteTokens"":17670,""totalCents"":10.7713}",false +1790272980000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":32947,""outputTokens"":9668,""cacheReadTokens"":175897,""cacheWriteTokens"":18929,""totalCents"":147.0455}",false +1790249280000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":30848,""outputTokens"":10449,""cacheReadTokens"":222288,""cacheWriteTokens"":19907,""totalCents"":156.2467}",false +1790258220000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":44023,""outputTokens"":11840,""cacheReadTokens"":263167,""cacheWriteTokens"":20541,""totalCents"":14.3376}",false +1790263860000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":43662,""outputTokens"":15171,""cacheReadTokens"":202792,""cacheWriteTokens"":32432,""totalCents"":54.1009}",false +1790269620000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":19366,""outputTokens"":3248,""cacheReadTokens"":93083,""cacheWriteTokens"":6341,""totalCents"":15.8522}",false +1790241960000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":18925,""outputTokens"":5887,""cacheReadTokens"":165540,""cacheWriteTokens"":10192,""totalCents"":7.1767}",false +1790272560000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":14870,""outputTokens"":4519,""cacheReadTokens"":94412,""cacheWriteTokens"":10643,""totalCents"":72.2519}",false +1790256240000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":17548,""outputTokens"":5907,""cacheReadTokens"":142839,""cacheWriteTokens"":9157,""totalCents"":6.6906}",false +1790238780000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":21262,""outputTokens"":4171,""cacheReadTokens"":136721,""cacheWriteTokens"":16429,""totalCents"":7.2154}",false +1790254260000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18036,""outputTokens"":5682,""cacheReadTokens"":124569,""cacheWriteTokens"":8136,""totalCents"":82.8875}",false +1790237040000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":15789,""outputTokens"":5223,""cacheReadTokens"":110963,""cacheWriteTokens"":11135,""totalCents"":6.1696}",false +1790266440000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":22384,""outputTokens"":5633,""cacheReadTokens"":172531,""cacheWriteTokens"":14053,""totalCents"":7.9735}",false +1790264700000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13776,""outputTokens"":4007,""cacheReadTokens"":80491,""cacheWriteTokens"":4965,""totalCents"":14.4199}",false +1790265660000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":11703,""outputTokens"":1888,""cacheReadTokens"":57330,""cacheWriteTokens"":7794,""totalCents"":10.9855}",false +1790275140000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11158,""outputTokens"":2569,""cacheReadTokens"":76270,""cacheWriteTokens"":5002,""totalCents"":3.5314}",false +1790250300000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13930,""outputTokens"":2630,""cacheReadTokens"":67111,""cacheWriteTokens"":9949,""totalCents"":13.8682}",false +1790274120000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":15647,""outputTokens"":3713,""cacheReadTokens"":112275,""cacheWriteTokens"":4727,""totalCents"":61.6179}",false +1790243460000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":27528,""outputTokens"":9002,""cacheReadTokens"":193144,""cacheWriteTokens"":9512,""totalCents"":31.1227}",false +1790264160000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14461,""outputTokens"":3960,""cacheReadTokens"":64267,""cacheWriteTokens"":4858,""totalCents"":4.28}",false +1790329560000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":40506,""outputTokens"":10985,""cacheReadTokens"":346155,""cacheWriteTokens"":12398,""totalCents"":174.6528}",false +1790364120000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":34970,""outputTokens"":6603,""cacheReadTokens"":185736,""cacheWriteTokens"":22356,""totalCents"":137.4043}",false +1790335800000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":29659,""outputTokens"":6391,""cacheReadTokens"":167828,""cacheWriteTokens"":14727,""totalCents"":9.0415}",false +1790359140000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17797,""outputTokens"":5934,""cacheReadTokens"":76017,""cacheWriteTokens"":9424,""totalCents"":80.2184}",false +1790341680000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":28546,""outputTokens"":8861,""cacheReadTokens"":123862,""cacheWriteTokens"":20214,""totalCents"":132.6056}",false +1790338740000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":23347,""outputTokens"":7824,""cacheReadTokens"":155530,""cacheWriteTokens"":11754,""totalCents"":27.8137}",false +1790334960000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":25688,""outputTokens"":7926,""cacheReadTokens"":137189,""cacheWriteTokens"":14497,""totalCents"":8.9232}",false +1790341080000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13049,""outputTokens"":2530,""cacheReadTokens"":114919,""cacheWriteTokens"":8859,""totalCents"":14.4794}",false +1790337720000,devon@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":15214,""outputTokens"":4266,""cacheReadTokens"":83906,""cacheWriteTokens"":7170,""totalCents"":4.9631}",false +1790355480000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":20780,""outputTokens"":6539,""cacheReadTokens"":107928,""cacheWriteTokens"":9619,""totalCents"":91.5499}",false +1790349900000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":9311,""outputTokens"":2212,""cacheReadTokens"":79952,""cacheWriteTokens"":4570,""totalCents"":10.2236}",false +1790336280000,devon@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10335,""outputTokens"":1734,""cacheReadTokens"":55462,""cacheWriteTokens"":4046,""totalCents"":35.5304}",false +1790349240000,devon@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":8958,""outputTokens"":2484,""cacheReadTokens"":60798,""cacheWriteTokens"":6846,""totalCents"":10.8046}",false +1790327460000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":7528,""outputTokens"":1239,""cacheReadTokens"":62871,""cacheWriteTokens"":2497,""totalCents"":27.7576}",false +1790329980000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11927,""outputTokens"":2456,""cacheReadTokens"":52556,""cacheWriteTokens"":3733,""totalCents"":40.9546}",false +1790335740000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11282,""outputTokens"":2111,""cacheReadTokens"":58828,""cacheWriteTokens"":6166,""totalCents"":3.3316}",false +1790343240000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":17354,""outputTokens"":3111,""cacheReadTokens"":117147,""cacheWriteTokens"":12816,""totalCents"":72.7724}",false +1790331240000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11912,""outputTokens"":2023,""cacheReadTokens"":72354,""cacheWriteTokens"":6915,""totalCents"":3.5883}",false +1790337180000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14815,""outputTokens"":4939,""cacheReadTokens"":119442,""cacheWriteTokens"":10356,""totalCents"":5.946}",false +1790349180000,Sam.Rivera@Example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":11535,""outputTokens"":3694,""cacheReadTokens"":61370,""cacheWriteTokens"":6850,""totalCents"":53.6454}",false +1790341740000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":31326,""outputTokens"":9502,""cacheReadTokens"":253833,""cacheWriteTokens"":13748,""totalCents"":11.1902}",false +1790340900000,Sam.Rivera@Example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":14041,""outputTokens"":2609,""cacheReadTokens"":99429,""cacheWriteTokens"":8618,""totalCents"":4.5192}",false +1790343360000,Sam.Rivera@Example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":30472,""outputTokens"":6242,""cacheReadTokens"":204934,""cacheWriteTokens"":18025,""totalCents"":31.412}",false +1790438760000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":5641,""outputTokens"":1915,""cacheReadTokens"":35503,""cacheWriteTokens"":2493,""totalCents"":1.9968}",false +1790448240000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":10431,""outputTokens"":2811,""cacheReadTokens"":45112,""cacheWriteTokens"":7082,""totalCents"":3.5039}",false +1790414580000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":9783,""outputTokens"":2997,""cacheReadTokens"":59932,""cacheWriteTokens"":7585,""totalCents"":12.0727}",false +1790417520000,casey@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":8274,""outputTokens"":2775,""cacheReadTokens"":43783,""cacheWriteTokens"":5522,""totalCents"":40.1158}",false +1790438940000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":6701,""outputTokens"":1148,""cacheReadTokens"":33552,""cacheWriteTokens"":4442,""totalCents"":2.0201}",false +1790439840000,casey@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":7225,""outputTokens"":2200,""cacheReadTokens"":53194,""cacheWriteTokens"":4073,""totalCents"":2.6436}",false +1790426100000,casey@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":10189,""outputTokens"":3449,""cacheReadTokens"":74740,""cacheWriteTokens"":4359,""totalCents"":12.107}",false +1790521440000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":13882,""outputTokens"":4844,""cacheReadTokens"":105706,""cacheWriteTokens"":8444,""totalCents"":17.7683}",false +1790532180000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7394,""outputTokens"":2425,""cacheReadTokens"":63853,""cacheWriteTokens"":3373,""totalCents"":9.0362}",false +1790512380000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10816,""outputTokens"":2891,""cacheReadTokens"":54070,""cacheWriteTokens"":4254,""totalCents"":43.1946}",false +1790501400000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7197,""outputTokens"":1667,""cacheReadTokens"":47306,""cacheWriteTokens"":2294,""totalCents"":6.939}",false +1790532360000,alex@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":7029,""outputTokens"":1405,""cacheReadTokens"":59850,""cacheWriteTokens"":5545,""totalCents"":8.0911}",false +1790529060000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":10364,""outputTokens"":1988,""cacheReadTokens"":75554,""cacheWriteTokens"":4245,""totalCents"":39.7988}",false +1790510580000,alex@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":11482,""outputTokens"":2711,""cacheReadTokens"":47521,""cacheWriteTokens"":4207,""totalCents"":3.2337}",false +1790505900000,alex@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":18808,""outputTokens"":4629,""cacheReadTokens"":166961,""cacheWriteTokens"":6852,""totalCents"":80.6569}",false +1790517060000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":6238,""outputTokens"":1082,""cacheReadTokens"":34527,""cacheWriteTokens"":2608,""totalCents"":22.0328}",false +1790530380000,finley@example.com,cursor-agent-demo,Included in Business,false,1.0,true,"{""inputTokens"":6349,""outputTokens"":2053,""cacheReadTokens"":49766,""cacheWriteTokens"":4066,""totalCents"":8.0019}",false +1790511600000,finley@example.com,cursor-max-demo,Included in Business,true,1.0,true,"{""inputTokens"":6090,""outputTokens"":1339,""cacheReadTokens"":25625,""cacheWriteTokens"":4142,""totalCents"":24.63}",false +1790515920000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":4341,""outputTokens"":741,""cacheReadTokens"":37675,""cacheWriteTokens"":1530,""totalCents"":1.2985}",false +1790514360000,finley@example.com,cursor-fast-demo,Included in Business,false,1.0,true,"{""inputTokens"":5035,""outputTokens"":760,""cacheReadTokens"":22332,""cacheWriteTokens"":3779,""totalCents"":1.5032}",false diff --git a/resources/startup-data-kit/ai-coding-spend/sample-data/generate.py b/resources/startup-data-kit/ai-coding-spend/sample-data/generate.py new file mode 100644 index 0000000..6c7a48a --- /dev/null +++ b/resources/startup-data-kit/ai-coding-spend/sample-data/generate.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +"""Regenerate the fake Claude Code and Cursor usage CSVs in this folder. + +Sample code: read it before you run it. + +Every value is invented: the people, the organisation, the token counts and the +per-token rates. Nothing is derived from real usage or real pricing. The seed is +fixed, so the output is identical on every run. + + python3 generate.py + +Standard library only. +""" + +from __future__ import annotations + +import csv +import datetime +import json +import pathlib +import random + +HERE = pathlib.Path(__file__).resolve().parent +RNG = random.Random(6682) + +START = datetime.date(2026, 9, 14) +DAYS = 14 + +ORG_ID = "org_example_demo" + +# Fictional people on the reserved example.com domain. "claude" and "cursor" +# say which tool each uses; "weight" scales how heavily. +PEOPLE = [ + {"email": "alex@example.com", "claude": True, "cursor": True, "weight": 1.6}, + {"email": "blair@example.com", "claude": True, "cursor": False, "weight": 1.2}, + {"email": "casey@example.com", "claude": False, "cursor": True, "weight": 1.0}, + {"email": "devon@example.com", "claude": True, "cursor": True, "weight": 0.8}, + {"email": "emery@example.com", "claude": True, "cursor": False, "weight": 0.4}, + {"email": "finley@example.com", "claude": False, "cursor": True, "weight": 0.7}, + # Cursor reports this person with different casing. The template lowercases + # emails, so both platforms still join to one user. + {"email": "sam.rivera@example.com", "cursor_email": "Sam.Rivera@Example.com", + "claude": True, "cursor": True, "weight": 1.1}, +] + +# A CI key, so the data shows an API-key actor counted alongside people. +API_KEY = "ci-review-bot" + +# Invented rates in US cents per million tokens: input, output, cache read, +# cache write. Not any vendor's price list. +CLAUDE_RATES = { + "claude-sonnet-demo": (300, 1500, 30, 375), + "claude-opus-demo": (1500, 7500, 150, 1875), + "claude-haiku-demo": (100, 500, 10, 125), +} +CURSOR_MODELS = ["cursor-fast-demo", "cursor-agent-demo", "cursor-max-demo"] +CURSOR_RATES = { + "cursor-fast-demo": (100, 400, 10, 125), + "cursor-agent-demo": (300, 1500, 30, 375), + "cursor-max-demo": (1200, 6000, 120, 1500), +} + + +def cents(rates: tuple[int, int, int, int], tokens: tuple[int, int, int, int]) -> float: + return round(sum(r * t for r, t in zip(rates, tokens)) / 1_000_000, 4) + + +def tokens(scale: float) -> tuple[int, int, int, int]: + inp = int(RNG.uniform(40_000, 120_000) * scale) + out = int(inp * RNG.uniform(0.15, 0.35)) + cache_read = int(inp * RNG.uniform(4, 9)) + cache_write = int(inp * RNG.uniform(0.3, 0.8)) + return inp, out, cache_read, cache_write + + +def epoch_ms(day: datetime.date, hour: int = 0, minute: int = 0) -> int: + moment = datetime.datetime(day.year, day.month, day.day, hour, minute, + tzinfo=datetime.timezone.utc) + return int(moment.timestamp() * 1000) + + +def write(name: str, header: list[str], rows: list[list[object]]) -> None: + with (HERE / name).open("w", newline="", encoding="utf-8") as f: + writer = csv.writer(f, lineterminator="\n") + writer.writerow(header) + writer.writerows(rows) + + +def main() -> None: + claude_rows: list[list[object]] = [] + cursor_daily: list[list[object]] = [] + cursor_events: list[list[object]] = [] + + for offset in range(DAYS): + day = START + datetime.timedelta(days=offset) + weekend = day.weekday() >= 5 + second_week = offset >= 7 + + for person in PEOPLE: + active_chance = 0.25 if weekend else 0.9 + scale = person["weight"] * (0.4 if weekend else 1.0) + + if person["claude"] and RNG.random() < active_chance: + # In the second week devon moves most work to the expensive + # model, so estimated cost jumps while tokens barely move. + if person["email"] == "devon@example.com" and second_week: + models = "claude-opus-demo,claude-sonnet-demo" + rate = CLAUDE_RATES["claude-opus-demo"] + elif RNG.random() < 0.15: + models = "claude-haiku-demo" + rate = CLAUDE_RATES["claude-haiku-demo"] + else: + models = "claude-sonnet-demo" + rate = CLAUDE_RATES["claude-sonnet-demo"] + terminals = ["vscode"] if RNG.random() < 0.6 else ["vscode", "iTerm.app"] + for terminal in terminals: + t = tokens(scale / len(terminals)) + added = int(RNG.uniform(80, 600) * scale) + claude_rows.append([ + day.isoformat(), "user_actor", person["email"], ORG_ID, + "subscription", terminal, RNG.randint(1, 5), + added, int(added * RNG.uniform(0.2, 0.6)), + RNG.randint(0, 3), RNG.randint(0, 1), *t, cents(rate, t), models, + ]) + + if person["cursor"]: + active = RNG.random() < active_chance + email = person.get("cursor_email", person["email"]) + composer = RNG.randint(2, 15) if active else 0 + chat = RNG.randint(1, 10) if active else 0 + agent = RNG.randint(0, 12) if active else 0 + accepts = RNG.randint(5, 40) if active else 0 + rejects = RNG.randint(1, 15) if active else 0 + tabs_shown = RNG.randint(50, 400) if active else 0 + total_added = int(RNG.uniform(100, 900) * scale) if active else 0 + model = RNG.choice(CURSOR_MODELS[:2]) if active else "" + cursor_daily.append([ + epoch_ms(day), email, str(active).lower(), + total_added, int(total_added * 0.4), + int(total_added * 0.6), int(total_added * 0.2), + accepts + rejects, accepts, rejects, + tabs_shown, int(tabs_shown * RNG.uniform(0.2, 0.45)), + composer, chat, agent, RNG.randint(0, 6) if active else 0, + composer + chat + agent, 0, 0, 0, model, + ".ts" if active else "", ".py" if active else "", "9.9.0-demo", + ]) + if active: + for _ in range(RNG.randint(3, 8)): + model = RNG.choice(CURSOR_MODELS) + t = tokens(scale / 4) + usage = { + "inputTokens": t[0], "outputTokens": t[1], + "cacheReadTokens": t[2], "cacheWriteTokens": t[3], + "totalCents": cents(CURSOR_RATES[model], t), + } + cursor_events.append([ + epoch_ms(day, RNG.randint(8, 19), RNG.randint(0, 59)), + email, model, "Included in Business", + str(model == "cursor-max-demo").lower(), 1.0, "true", + json.dumps(usage, separators=(",", ":")), "false", + ]) + + if not weekend: + t = tokens(0.5) + claude_rows.append([ + day.isoformat(), "api_actor", API_KEY, ORG_ID, "api", "non-interactive", + RNG.randint(10, 30), 0, 0, 0, 0, *t, + cents(CLAUDE_RATES["claude-haiku-demo"], t), "claude-haiku-demo", + ]) + + write("claude_code_usage.csv", [ + "date", "actor_type", "actor_id", "organization_id", "customer_type", + "terminal_type", "num_sessions", "lines_added", "lines_removed", + "commits_by_claude_code", "pull_requests_by_claude_code", + "total_input_tokens", "total_output_tokens", "total_cache_read_tokens", + "total_cache_creation_tokens", "total_estimated_cost_cents", "models_used", + ], claude_rows) + write("cursor_daily_usage.csv", [ + "date", "email", "isActive", "totalLinesAdded", "totalLinesDeleted", + "acceptedLinesAdded", "acceptedLinesDeleted", "totalApplies", + "totalAccepts", "totalRejects", "totalTabsShown", "totalTabsAccepted", + "composerRequests", "chatRequests", "agentRequests", "cmdkUsages", + "subscriptionIncludedReqs", "apiKeyReqs", "usageBasedReqs", "bugbotUsages", + "mostUsedModel", "applyMostUsedExtension", "tabMostUsedExtension", + "clientVersion", + ], cursor_daily) + write("cursor_usage_events.csv", [ + "timestamp", "userEmail", "model", "kind", "maxMode", "requestsCosts", + "isTokenBasedCall", "tokenUsage", "isFreeBugbot", + ], cursor_events) + + print(f"{len(claude_rows)} Claude Code rows, {len(cursor_daily)} Cursor daily rows, " + f"{len(cursor_events)} Cursor events") + + +if __name__ == "__main__": + main() diff --git a/tests/check.py b/tests/check.py index 38afd3c..ebae33c 100755 --- a/tests/check.py +++ b/tests/check.py @@ -14,6 +14,7 @@ from __future__ import annotations import datetime +import json import pathlib import re import sys @@ -21,6 +22,7 @@ REPO = pathlib.Path(__file__).resolve().parent.parent RESOURCES = REPO / "resources" README = REPO / "README.md" +MARKETPLACE = REPO / ".claude-plugin" / "marketplace.json" VALID_STATUS = {"stable", "experimental", "community"} VALID_RISK = {"read-only", "approval-required", "write-capable"} @@ -50,6 +52,10 @@ ("GCP service account", r"[a-z0-9-]+@[a-z0-9-]+\.iam\.gserviceaccount\.com"), ] +# Sample data must be invented. Every email address in it has to sit on a +# domain reserved for examples, so a real address pasted in fails the build. +SAMPLE_EMAIL_DOMAINS = {"example.com", "example.org", "example.net"} + # Lines carrying this marker are exempt, for the rare case where such a string # genuinely belongs in documentation. ALLOW_MARKER = "check: allow" @@ -210,7 +216,7 @@ def check_internal_identifiers() -> None: for path in sorted(REPO.rglob("*")): if not path.is_file() or any(p in {".git", ".context"} for p in path.parts): continue - if path.suffix not in {".md", ".py", ".yml", ".yaml", ".json", ".toml", ".sh", ".txt"}: + if path.suffix not in {".md", ".py", ".yml", ".yaml", ".json", ".toml", ".sh", ".txt", ".csv", ".tape"}: continue try: text = path.read_text(encoding="utf-8") @@ -243,6 +249,60 @@ def check_shared_files() -> None: err(copy, f"differs from {copies[0].relative_to(REPO)}; shared copies must be identical") +def check_marketplace() -> None: + """The Claude Code marketplace loads only the skill folders it lists, and + skills.sh stops searching the whole tree once a manifest exists. So a skill + missing from the manifest is invisible to both install methods.""" + if not MARKETPLACE.exists(): + err(".claude-plugin/marketplace.json", "missing; it is how both one-line installs find skills") + return + try: + manifest = json.loads(MARKETPLACE.read_text(encoding="utf-8")) + except json.JSONDecodeError as exc: + err(MARKETPLACE, f"not valid JSON: {exc}") + return + for key in ("name", "owner", "plugins"): + if key not in manifest: + err(MARKETPLACE, f"missing required field '{key}'") + listed: dict[str, str] = {} + names: set[str] = set() + for plugin in manifest.get("plugins", []): + name = plugin.get("name", "") + if not name or "source" not in plugin: + err(MARKETPLACE, f"plugin {name or '(unnamed)'} needs a name and a source") + if name in names: + err(MARKETPLACE, f"plugin name '{name}' is listed twice") + names.add(name) + for skill in plugin.get("skills", []): + rel = skill.removeprefix("./").rstrip("/") + if not (REPO / rel / "SKILL.md").exists(): + err(MARKETPLACE, f"plugin '{name}' lists '{skill}', which has no SKILL.md") + if rel in listed: + err(MARKETPLACE, f"'{skill}' is in both '{listed[rel]}' and '{name}'") + listed[rel] = name + for skill in sorted(RESOURCES.rglob("SKILL.md")): + rel = str(skill.parent.relative_to(REPO)) + if rel not in listed: + err(MARKETPLACE, f"'{rel}' is not listed in any plugin, so neither install method finds it") + + +def check_sample_data() -> None: + """Sample data ships with the repository, so it must be visibly invented.""" + for path in sorted(RESOURCES.rglob("sample-data/*")): + if not path.is_file(): + continue + try: + text = path.read_text(encoding="utf-8") + except UnicodeDecodeError: + err(path, "sample data must be plain text so it can be reviewed") + continue + for line_no, line in enumerate(text.splitlines(), 1): + for domain in re.findall(r"[\w.+-]+@([\w-]+(?:\.[\w-]+)+)", line): + if domain.lower() not in SAMPLE_EMAIL_DOMAINS: + err(path, f"line {line_no}: email on '{domain}'; sample data may only use " + f"{', '.join(sorted(SAMPLE_EMAIL_DOMAINS))}") + + def check_forbidden_files() -> None: for path in REPO.rglob("*"): if ".git" in path.parts or not path.is_file(): @@ -266,6 +326,8 @@ def main() -> int: check_links() check_internal_identifiers() check_shared_files() + check_marketplace() + check_sample_data() check_forbidden_files() docs = len(list(RESOURCES.rglob("*.md")))