feat: add Fireworks AI plugin for usage tracking and billing metrics#359
feat: add Fireworks AI plugin for usage tracking and billing metrics#359sayuru-akash wants to merge 1 commit intorobinebers:mainfrom
Conversation
- Implemented the Fireworks AI plugin to track serverless usage, prompt tokens, generated tokens, monthly spend, and budget. - Added API calls to list accounts and quotas, and export billing metrics. - Integrated macOS Keychain and environment variable support for API key management. - Created a detailed documentation file for the Fireworks AI plugin. - Added SVG icon for the Fireworks AI plugin. - Developed comprehensive tests to ensure functionality and error handling.
🤖 Augment PR SummarySummary: Adds a new Fireworks AI provider plugin so OpenUsage can show Fireworks account health, spend/budget, and serverless token usage. Changes:
Technical Notes: Billing exports use UTC date-only windows ("Last 30 days") and the UI falls back to spend/budget when token exports are unavailable. 🤖 Was this summary useful? React with 👍 or 👎 |
| - [**Copilot**](docs/providers/copilot.md) / premium, chat, completions | ||
| - [**Cursor**](docs/providers/cursor.md) / credits, total usage, auto usage, API usage, on-demand, CLI auth | ||
| - [**Factory / Droid**](docs/providers/factory.md) / standard, premium tokens | ||
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend |
There was a problem hiding this comment.
| | Metric | Source | Scope | Format | Notes | | ||
| | --- | --- | --- | --- | --- | | ||
| | Serverless usage | billing export or aggregate token counter | overview | text | Main cumulative usage line, shown as a compact token total like `104.85M tokens` | | ||
| | Prompt tokens | billing export or token counter | overview | text | Prompt/input token total for the selected rolling window | |
There was a problem hiding this comment.
docs/providers/fireworks-ai.md:19 — The docs say Prompt/Generated tokens come from “billing export or token counter”, but the implementation only fills these from billing export (quota fallback is only used for an aggregate total). This may mislead users when firectl isn’t available.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| generatedTokens += num(row.completion_tokens || row.completionTokens) || 0 | ||
| } | ||
| const totalTokens = promptTokens + generatedTokens | ||
| return totalTokens > 0 |
There was a problem hiding this comment.
plugins/fireworks-ai/plugin.js:300 — loadBillingUsage treats a valid 0-token window as empty, which later renders usage as unavailable/no-data instead of showing 0 tokens. That can misrepresent legitimate zero-usage accounts.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| "billing", | ||
| "export-metrics", | ||
| "--api-key", | ||
| opts.api_key.trim(), |
There was a problem hiding this comment.
src-tauri/src/plugin_engine/host_api.rs:2062 — Passing the Fireworks API key via firectl --api-key ... exposes the secret in local process listings and potentially crash/diagnostic reports. This is a sensitive-secret handling risk for a desktop app.
Severity: high
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59d328eacb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "--filename", | ||
| file_name.as_str(), | ||
| ]) | ||
| .output(); |
There was a problem hiding this comment.
Add timeout around firectl billing export subprocess
Avoid calling Command::output() without a timeout here: if firectl billing export-metrics stalls (for example due to DNS/proxy/network hangs), this probe thread can block indefinitely and the batch countdown in src-tauri/src/lib.rs never reaches completion, so users can get a probe batch that never finishes. Please run this command with bounded wait/kill logic (like the existing ccusage runner path) so one stuck export cannot wedge refreshes.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a new Fireworks AI provider plugin to OpenUsage, including host/runtime support for pulling usage/billing metrics and documentation so users can configure authentication and understand reported metrics.
Changes:
- Added a Fireworks AI plugin (manifest, implementation, icon) that queries Fireworks account/quota APIs and optionally computes rolling serverless token usage via
firectl billing export-metrics. - Extended the Tauri plugin host API to expose
host.fireworks.exportBillingMetrics()to plugins, whitelistFIREWORKS_API_KEY, and redact Fireworks account IDs from logged URLs. - Added provider docs, README provider list entry, and Vitest coverage for the new plugin + host changes.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src-tauri/src/plugin_engine/runtime.rs | Calls the new Fireworks wrapper patch during plugin probe setup. |
| src-tauri/src/plugin_engine/host_api.rs | Adds env allowlist entry, URL redaction for /accounts/{id}, Fireworks host API injection, and firectl runner integration + tests. |
| README.md | Adds Fireworks AI to the provider list. |
| plugins/test-helpers.js | Extends the mock host context with host.fireworks.exportBillingMetrics. |
| plugins/fireworks-ai/plugin.test.js | Comprehensive tests for auth resolution, quota parsing, billing export integration, and error paths. |
| plugins/fireworks-ai/plugin.json | New plugin manifest defining Fireworks AI lines/labels/scopes and metadata. |
| plugins/fireworks-ai/plugin.js | Fireworks AI plugin implementation (accounts, quotas, billing CSV parsing, output formatting). |
| plugins/fireworks-ai/icon.svg | Provider icon asset. |
| docs/providers/fireworks-ai.md | Setup + behavior documentation for the Fireworks AI provider. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -239,6 +242,12 @@ fn redact_url(url: &str) -> String { | |||
| "login", | |||
| ]; | |||
|
|
|||
| let url = account_path_pattern | |||
| .replace_all(url, |caps: ®ex_lite::Captures| { | |||
| format!("{}{}", &caps["prefix"], redact_value(&caps["value"])) | |||
| }) | |||
| .to_string(); | |||
There was a problem hiding this comment.
redact_url now compiles a new regex_lite::Regex on every call. Since redact_url is invoked for every plugin HTTP request log line, this adds avoidable per-request overhead. Consider moving the regex into a static (e.g., OnceLock<Regex>) and reusing it, similar to other cached values in this module.
| fn resolve_firectl_runner() -> Option<String> { | ||
| for candidate in firectl_runner_candidates() { | ||
| if Command::new(candidate) | ||
| .arg("--help") | ||
| .status() | ||
| .map(|status| status.success()) | ||
| .unwrap_or(false) | ||
| { | ||
| return Some(candidate.to_string()); | ||
| } | ||
| } | ||
| None |
There was a problem hiding this comment.
resolve_firectl_runner() runs firectl --help for each probe call. This can become expensive and also adds repeated process spawning even when the runner location never changes during the app session. Consider caching the resolved runner path (including negative results) in a OnceLock<Option<String>> and reusing it across calls.
| fn resolve_firectl_runner() -> Option<String> { | |
| for candidate in firectl_runner_candidates() { | |
| if Command::new(candidate) | |
| .arg("--help") | |
| .status() | |
| .map(|status| status.success()) | |
| .unwrap_or(false) | |
| { | |
| return Some(candidate.to_string()); | |
| } | |
| } | |
| None | |
| static FIRECTL_RUNNER: OnceLock<Option<String>> = OnceLock::new(); | |
| fn resolve_firectl_runner() -> Option<String> { | |
| FIRECTL_RUNNER | |
| .get_or_init(|| { | |
| for candidate in firectl_runner_candidates() { | |
| if Command::new(candidate) | |
| .arg("--help") | |
| .status() | |
| .map(|status| status.success()) | |
| .unwrap_or(false) | |
| { | |
| return Some(candidate.to_string()); | |
| } | |
| } | |
| None | |
| }) | |
| .clone() |
| let result = Command::new(&program) | ||
| .current_dir(&temp_dir) | ||
| .args([ | ||
| "billing", | ||
| "export-metrics", | ||
| "--api-key", | ||
| opts.api_key.trim(), | ||
| "--account-id", | ||
| opts.account_id.trim(), | ||
| "--start-time", | ||
| opts.start_time.trim(), | ||
| "--end-time", | ||
| opts.end_time.trim(), | ||
| "--filename", | ||
| file_name.as_str(), | ||
| ]) | ||
| .output(); |
There was a problem hiding this comment.
The Fireworks API key is passed to firectl via the --api-key command-line argument. On many OSes this can be observed by other local processes via process listings, which is a credential-leak risk. If firectl supports reading the key from an environment variable or stdin, prefer that; otherwise consider documenting this limitation and/or using a more isolated execution strategy.
| let result = Command::new(&program) | |
| .current_dir(&temp_dir) | |
| .args([ | |
| "billing", | |
| "export-metrics", | |
| "--api-key", | |
| opts.api_key.trim(), | |
| "--account-id", | |
| opts.account_id.trim(), | |
| "--start-time", | |
| opts.start_time.trim(), | |
| "--end-time", | |
| opts.end_time.trim(), | |
| "--filename", | |
| file_name.as_str(), | |
| ]) | |
| .output(); | |
| let mut command = Command::new(&program); | |
| command.current_dir(&temp_dir); | |
| command.env("FIREWORKS_API_KEY", opts.api_key.trim()); | |
| command.args([ | |
| "billing", | |
| "export-metrics", | |
| "--account-id", | |
| opts.account_id.trim(), | |
| "--start-time", | |
| opts.start_time.trim(), | |
| "--end-time", | |
| opts.end_time.trim(), | |
| "--filename", | |
| file_name.as_str(), | |
| ]); | |
| let result = command.output(); |
| - [**Copilot**](docs/providers/copilot.md) / premium, chat, completions | ||
| - [**Cursor**](docs/providers/cursor.md) / credits, total usage, auto usage, API usage, on-demand, CLI auth | ||
| - [**Factory / Droid**](docs/providers/factory.md) / standard, premium tokens | ||
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend |
There was a problem hiding this comment.
README entry says “prompt/generated TPS”, but the plugin surfaces prompt/generated token totals (and the docs explicitly note it does not ship token-per-second bars). Please update this line to avoid implying throughput metrics.
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend | |
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated tokens, monthly spend |
| | Metric | Source | Scope | Format | Notes | | ||
| | --- | --- | --- | --- | --- | | ||
| | Serverless usage | billing export or aggregate token counter | overview | text | Main cumulative usage line, shown as a compact token total like `104.85M tokens` | | ||
| | Prompt tokens | billing export or token counter | overview | text | Prompt/input token total for the selected rolling window | | ||
| | Generated tokens | billing export or token counter | overview | text | Generated/output token total for the selected rolling window | | ||
| | Month spend | `monthly-spend-usd.usage` | overview | text | Current calendar-month billable spend | | ||
| | Budget | `monthly-spend-usd.value` / `maxValue` | detail | text | Configured monthly budget plus the tier cap | | ||
| | Status | account `state` / `suspendState` | detail | badge | Only shown when the account is not in a healthy state | |
There was a problem hiding this comment.
The markdown table under “Plugin Metrics” uses || at the start of each row, which renders as an extra empty column in most markdown parsers. Use a standard table format with single | separators so the table renders correctly.
| | Serverless usage | billing export or aggregate token counter | overview | text | Main cumulative usage line, shown as a compact token total like `104.85M tokens` | | ||
| | Prompt tokens | billing export or token counter | overview | text | Prompt/input token total for the selected rolling window | | ||
| | Generated tokens | billing export or token counter | overview | text | Generated/output token total for the selected rolling window | | ||
| | Month spend | `monthly-spend-usd.usage` | overview | text | Current calendar-month billable spend | | ||
| | Budget | `monthly-spend-usd.value` / `maxValue` | detail | text | Configured monthly budget plus the tier cap | | ||
| | Status | account `state` / `suspendState` | detail | badge | Only shown when the account is not in a healthy state | |
There was a problem hiding this comment.
Docs claim Prompt/Generated tokens can come from “billing export or token counter”, but the current implementation only populates these lines from the billing-export CSV (aggregate quota fallback is only used for total tokens). Either update the docs to match the implementation or extend the plugin to populate prompt/generated from quota fields when available.
| function lastFinite(values) { | ||
| for (let i = 0; i < values.length; i += 1) { | ||
| if (Number.isFinite(values[i])) return values[i] | ||
| } | ||
| return null | ||
| } |
There was a problem hiding this comment.
lastFinite() returns the first finite number it encounters, not the last. This is a naming mismatch that can cause confusion when maintaining the quota normalization logic. Consider renaming it to something like firstFinite/pickFirstFinite or adjusting the implementation to match the current name.
There was a problem hiding this comment.
6 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src-tauri/src/plugin_engine/host_api.rs">
<violation number="1" location="src-tauri/src/plugin_engine/host_api.rs:31">
P1: Global allowlisting of `FIREWORKS_API_KEY` exposes a sensitive credential to all plugins because env access is not scoped per plugin.</violation>
<violation number="2" location="src-tauri/src/plugin_engine/host_api.rs:2062">
P1: Fireworks API key is passed in child-process argv (`--api-key <secret>`), creating credential exposure risk via process inspection/log surfaces.</violation>
<violation number="3" location="src-tauri/src/plugin_engine/host_api.rs:2072">
P1: `Command::output()` has no timeout — if `firectl billing export-metrics` hangs (DNS/network issues), the probe thread blocks indefinitely and the batch never finishes. Add bounded wait/kill logic similar to how other external command runners in this codebase handle subprocess timeouts.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:34">
P2: README documents Fireworks metrics as TPS, but the plugin and provider docs expose prompt/generated token totals, creating a user-facing contract mismatch.</violation>
</file>
<file name="plugins/fireworks-ai/plugin.js">
<violation number="1" location="plugins/fireworks-ai/plugin.js:36">
P3: `lastFinite()` iterates forward and returns the **first** finite number, not the last. The name is misleading and will confuse future maintainers. Rename to `firstFinite` or change the loop to iterate backwards.</violation>
<violation number="2" location="plugins/fireworks-ai/plugin.js:302">
P2: Zero-token billing exports are incorrectly marked as non-ok, causing valid zero usage to be shown as unavailable/error state.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| "billing", | ||
| "export-metrics", | ||
| "--api-key", | ||
| opts.api_key.trim(), |
There was a problem hiding this comment.
P1: Fireworks API key is passed in child-process argv (--api-key <secret>), creating credential exposure risk via process inspection/log surfaces.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src-tauri/src/plugin_engine/host_api.rs, line 2062:
<comment>Fireworks API key is passed in child-process argv (`--api-key <secret>`), creating credential exposure risk via process inspection/log surfaces.</comment>
<file context>
@@ -1992,6 +2002,164 @@ pub fn patch_ccusage_wrapper(ctx: &rquickjs::Ctx<'_>) -> rquickjs::Result<()> {
+ "billing",
+ "export-metrics",
+ "--api-key",
+ opts.api_key.trim(),
+ "--account-id",
+ opts.account_id.trim(),
</file context>
| "MINIMAX_CN_API_KEY", | ||
| "SYNTHETIC_API_KEY", | ||
| "PI_CODING_AGENT_DIR", | ||
| "FIREWORKS_API_KEY", |
There was a problem hiding this comment.
P1: Global allowlisting of FIREWORKS_API_KEY exposes a sensitive credential to all plugins because env access is not scoped per plugin.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src-tauri/src/plugin_engine/host_api.rs, line 31:
<comment>Global allowlisting of `FIREWORKS_API_KEY` exposes a sensitive credential to all plugins because env access is not scoped per plugin.</comment>
<file context>
@@ -28,6 +28,7 @@ const WHITELISTED_ENV_VARS: [&str; 16] = [
"MINIMAX_CN_API_KEY",
"SYNTHETIC_API_KEY",
"PI_CODING_AGENT_DIR",
+ "FIREWORKS_API_KEY",
];
</file context>
| "--filename", | ||
| file_name.as_str(), | ||
| ]) | ||
| .output(); |
There was a problem hiding this comment.
P1: Command::output() has no timeout — if firectl billing export-metrics hangs (DNS/network issues), the probe thread blocks indefinitely and the batch never finishes. Add bounded wait/kill logic similar to how other external command runners in this codebase handle subprocess timeouts.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src-tauri/src/plugin_engine/host_api.rs, line 2072:
<comment>`Command::output()` has no timeout — if `firectl billing export-metrics` hangs (DNS/network issues), the probe thread blocks indefinitely and the batch never finishes. Add bounded wait/kill logic similar to how other external command runners in this codebase handle subprocess timeouts.</comment>
<file context>
@@ -1992,6 +2002,164 @@ pub fn patch_ccusage_wrapper(ctx: &rquickjs::Ctx<'_>) -> rquickjs::Result<()> {
+ "--filename",
+ file_name.as_str(),
+ ])
+ .output();
+
+ let read_csv = || std::fs::read_to_string(&output_path).ok();
</file context>
| - [**Copilot**](docs/providers/copilot.md) / premium, chat, completions | ||
| - [**Cursor**](docs/providers/cursor.md) / credits, total usage, auto usage, API usage, on-demand, CLI auth | ||
| - [**Factory / Droid**](docs/providers/factory.md) / standard, premium tokens | ||
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend |
There was a problem hiding this comment.
P2: README documents Fireworks metrics as TPS, but the plugin and provider docs expose prompt/generated token totals, creating a user-facing contract mismatch.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 34:
<comment>README documents Fireworks metrics as TPS, but the plugin and provider docs expose prompt/generated token totals, creating a user-facing contract mismatch.</comment>
<file context>
@@ -31,6 +31,7 @@ OpenUsage lives in your menu bar and shows you how much of your AI coding subscr
- [**Copilot**](docs/providers/copilot.md) / premium, chat, completions
- [**Cursor**](docs/providers/cursor.md) / credits, total usage, auto usage, API usage, on-demand, CLI auth
- [**Factory / Droid**](docs/providers/factory.md) / standard, premium tokens
+- [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend
- [**Gemini**](docs/providers/gemini.md) / pro, flash, workspace/free/paid tier
- [**JetBrains AI Assistant**](docs/providers/jetbrains-ai-assistant.md) / quota, remaining
</file context>
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated TPS, monthly spend | |
| - [**Fireworks AI**](docs/providers/fireworks-ai.md) / serverless usage, prompt/generated tokens, monthly spend |
| const totalTokens = promptTokens + generatedTokens | ||
| return totalTokens > 0 | ||
| ? { status: "ok", label: window.label, promptTokens, generatedTokens, totalTokens } | ||
| : { status: "empty" } |
There was a problem hiding this comment.
P2: Zero-token billing exports are incorrectly marked as non-ok, causing valid zero usage to be shown as unavailable/error state.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At plugins/fireworks-ai/plugin.js, line 302:
<comment>Zero-token billing exports are incorrectly marked as non-ok, causing valid zero usage to be shown as unavailable/error state.</comment>
<file context>
@@ -0,0 +1,369 @@
+ const totalTokens = promptTokens + generatedTokens
+ return totalTokens > 0
+ ? { status: "ok", label: window.label, promptTokens, generatedTokens, totalTokens }
+ : { status: "empty" }
+ }
+
</file context>
| return raw ? raw.split("/").filter(Boolean).pop() || null : null | ||
| } | ||
|
|
||
| function lastFinite(values) { |
There was a problem hiding this comment.
P3: lastFinite() iterates forward and returns the first finite number, not the last. The name is misleading and will confuse future maintainers. Rename to firstFinite or change the loop to iterate backwards.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At plugins/fireworks-ai/plugin.js, line 36:
<comment>`lastFinite()` iterates forward and returns the **first** finite number, not the last. The name is misleading and will confuse future maintainers. Rename to `firstFinite` or change the loop to iterate backwards.</comment>
<file context>
@@ -0,0 +1,369 @@
+ return raw ? raw.split("/").filter(Boolean).pop() || null : null
+ }
+
+ function lastFinite(values) {
+ for (let i = 0; i < values.length; i += 1) {
+ if (Number.isFinite(values[i])) return values[i]
</file context>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59d328eacb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| maxValue: num(raw.maxValue || raw.max_value), | ||
| usage: lastFinite([ | ||
| num(raw.usage), | ||
| num(raw.currentUsage || raw.current_usage), | ||
| num(raw.consumedValue || raw.consumed_value), |
There was a problem hiding this comment.
Preserve zero-valued quotas when reading Fireworks fields
normalizeQuota uses raw.maxValue || raw.max_value and similar || fallbacks for usage fields, which treats legitimate 0 values as missing. When Fireworks returns currentUsage: 0 or maxValue: 0 (common at reset boundaries or new accounts), those values are converted to null, so downstream logic can hide spend/usage lines or show fallback states even though the API returned valid data. Use nullish checks (??) or explicit undefined handling so zero remains zero.
Useful? React with 👍 / 👎.
| const totalTokens = (billingUsage && billingUsage.status === "ok" && billingUsage.totalTokens) || tokenAmount(totalTokensQuota) || null | ||
| if (totalTokens !== null && totalTokens > 0) { | ||
| lines.push(ctx.line.text({ label: "Serverless usage", value: formatCompactCount(totalTokens) + " tokens", subtitle: billingUsage && billingUsage.status === "ok" ? billingUsage.label : "Tokens reported by Fireworks" })) | ||
| } else if (billingUsage && billingUsage.status !== "ok") { |
There was a problem hiding this comment.
Show zero token totals instead of fallback messaging
The serverless total uses ... || tokenAmount(totalTokensQuota) || null and then only renders when totalTokens > 0, so a real 0 token total is treated as absent and falls into the “Unavailable” fallback path whenever billing export is not ok. This misreports a valid zero-usage state (e.g., fresh account/window) as missing data. Treat 0 as a valid total and render 0 tokens rather than fallback text.
Useful? React with 👍 / 👎.
Description
This pull request introduces a new provider plugin for Fireworks AI, enabling users to track their Fireworks AI usage directly within OpenUsage.
The integration is built on Fireworks AI's official non-browser surfaces and does not depend on browser login or session state. It fetches account details and quotas from the Fireworks API, and uses the official
firectl billing export-metricspath to compute rolling token usage for serverless inference.The provider currently calculates and displays the most truthful metrics available from the validated account shape:
Authentication is supported via both macOS Keychain and environment variables, ensuring secure and flexible API key management.
A complete plugin manifest, documentation, icon assets, shared host/runtime support, and comprehensive test coverage have also been included.
Fireworks AI Integration
What Else We Can Do In The Future
Related Issue
Fixes #352
Type of Change
Screenshot
Testing
bun run buildand it succeededbun run testand all tests passbun tauri devChecklist
mainbranchSummary by cubic
Adds a
fireworks-aiprovider plugin to track Fireworks usage and billing in OpenUsage. Shows serverless tokens, prompt/generated tokens, month spend, budget, and account health with API-key auth via macOS Keychain orFIREWORKS_API_KEY, using the officialfirectl billing export-metricspath when available.fireworks-aiplugin: lists accounts/quotas fromhttps://api.fireworks.ai/v1and picks a healthy account.fireworks.exportBillingMetricswrapper aroundfirectl; falls back to token quotas or spend-only.FIREWORKS_API_KEYallowlist, redacts/accounts/{id}in URLs, exposesfireworks.exportBillingMetricsto plugins.Written for commit 59d328e. Summary will update on new commits.