Skip to content

Commit 3f1ba7d

Browse files
committed
feat: added Neuralwatt provider usage to providers-quota extension
1 parent fd88e59 commit 3f1ba7d

4 files changed

Lines changed: 339 additions & 62 deletions

File tree

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
# Set your API keys here for the providers you want to monitor
1+
# Set your API keys here to override the ones from AiderDesk provider settings (optional)
22
SYNTHETIC_API_KEY=
33
ZAI_API_KEY=
4+
NEURALWATT_API_KEY=

packages/extensions/extensions/providers-quota-extension/README.md

Lines changed: 83 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
# Providers Quota Extension
22

3-
Displays API quota information for **Synthetic** and **Z.AI** providers in the AiderDesk task status bar. The extension automatically shows the relevant quota based on the active agent profile's provider.
3+
Displays API quota information for **Synthetic**, **Z.AI**, and **Neuralwatt** providers in the AiderDesk task status bar. The extension automatically shows the relevant quota based on the active agent profile's provider.
44

55
## Features
66

77
- **Synthetic Provider**: Shows used/limit with percentage and progress bar
88
- **Z.AI Provider**: Shows 5-hour and weekly usage percentages with progress bars
9+
- **Neuralwatt Provider**: Shows quota based on account type:
10+
- **Subscription**: kWh used/included with percentage and renewal date
11+
- **Pay-as-you-go**: Credits remaining/total with percentage
12+
- API keys are automatically loaded from AiderDesk provider settings
13+
- Optional `.env` file to override API keys
914
- Automatic provider detection based on active agent profile
1015
- Quota data cached for 1 minute to minimize API calls
1116

@@ -16,46 +21,42 @@ Displays API quota information for **Synthetic** and **Z.AI** providers in the A
1621
cp -r providers-quota-extension ~/.aider-desk/extensions/
1722
```
1823

19-
2. Create a `.env` file in the extension folder with your API key(s):
20-
```bash
21-
cd ~/.aider-desk/extensions/providers-quota-extension
22-
echo "SYNTHETIC_API_KEY=your_synthetic_key_here" > .env
23-
echo "ZAI_API_KEY=your_zai_key_here" >> .env
24-
```
25-
26-
3. Install the dotenv dependency:
24+
2. Install the dotenv dependency:
2725
```bash
2826
npm install
2927
```
3028

31-
4. Restart AiderDesk
29+
3. Restart AiderDesk
3230

3331
## Usage
3432

3533
The extension automatically displays quota information based on the active agent profile:
3634

3735
| Provider | Display Format |
3836
|----------|---------------|
39-
| `synthetic` | `Quota: 54/100 (54%)` with progress bar |
40-
| `zai-plan` | `Z.AI: 5h: 12% Weekly: 45%` with two progress bars |
37+
| `synthetic` | `Synthetic: 54/100 (54%)` |
38+
| `zai-plan` | `Z.ai: 5 Hours: 12% \| Weekly: 45%` |
39+
| `neuralwatt` (subscription) | `Neuralwatt: 13.90/20.0 kWh (70%)` |
40+
| `neuralwatt` (pay-as-you-go) | `Neuralwatt: $32.68/$52.34 (62%)` |
4141

4242
If the agent profile's provider doesn't match a configured provider, no quota is displayed.
4343

4444
## Configuration
4545

46-
### Environment Variables
46+
### API Keys
4747

48-
Create a `.env` file in the extension folder (`~/.aider-desk/extensions/providers-quota-extension/.env`):
48+
API keys are **automatically loaded from AiderDesk provider settings** — no manual configuration required. Simply ensure your API keys are set in the AiderDesk Providers settings page.
49+
50+
To override the API keys from AiderDesk settings, create a `.env` file in the extension folder (`~/.aider-desk/extensions/providers-quota-extension/.env`):
4951

5052
```env
51-
# For Synthetic provider (optional)
53+
# Override API keys (optional — only needed to override AiderDesk settings)
5254
SYNTHETIC_API_KEY=your_synthetic_api_key
53-
54-
# For Z.AI provider (optional)
5555
ZAI_API_KEY=your_zai_api_key
56+
NEURALWATT_API_KEY=your_neuralwatt_api_key
5657
```
5758

58-
You can configure either or both providers. Only configure the ones you use.
59+
You can configure any combination of providers. Only configure the ones you use.
5960

6061
### Multiple Environment Files
6162

@@ -112,12 +113,53 @@ The extension supports multiple `.env` files loaded in priority order (later fil
112113
}
113114
```
114115

116+
### Neuralwatt API
117+
118+
- **Endpoint**: `https://api.neuralwatt.com/v1/quota`
119+
- **Response Format** (subscription):
120+
```json
121+
{
122+
"snapshot_at": "2026-04-16T18:30:00Z",
123+
"balance": {
124+
"credits_remaining_usd": 32.6774,
125+
"total_credits_usd": 52.34,
126+
"credits_used_usd": 19.6626,
127+
"accounting_method": "energy"
128+
},
129+
"subscription": {
130+
"plan": "standard",
131+
"status": "active",
132+
"billing_interval": "month",
133+
"current_period_start": "2026-04-11T05:05:25Z",
134+
"current_period_end": "2026-05-11T05:05:25Z",
135+
"auto_renew": true,
136+
"kwh_included": 20.0,
137+
"kwh_used": 13.9023,
138+
"kwh_remaining": 6.0977,
139+
"in_overage": false
140+
}
141+
}
142+
```
143+
- **Response Format** (pay-as-you-go — `subscription` is `null`):
144+
```json
145+
{
146+
"snapshot_at": "2026-04-16T18:30:00Z",
147+
"balance": {
148+
"credits_remaining_usd": 32.6774,
149+
"total_credits_usd": 52.34,
150+
"credits_used_usd": 19.6626,
151+
"accounting_method": "energy"
152+
},
153+
"subscription": null
154+
}
155+
```
156+
115157
## Troubleshooting
116158

117159
### Quota not displayed
118160

119-
1. Verify that the correct API key is set in `.env`
120-
2. Ensure the agent profile's provider matches (`synthetic` or `zai-plan`)
161+
1. Verify that the API key is set in AiderDesk Providers settings or `.env`
162+
2. Ensure the agent profile's provider matches (`synthetic`, `zai-plan`, or `neuralwatt`)
121163
3. Check AiderDesk logs for error messages
122164
4. Verify network connectivity to the API endpoints
123165

@@ -149,7 +191,7 @@ providers-quota-extension/
149191
├── index.ts # Main extension logic
150192
├── StatusBarComponent.jsx # React JSX for UI rendering
151193
├── package.json # Dependencies
152-
├── .env # API keys (create this)
194+
├── .env.template # Template for API key overrides (create .env from this)
153195
└── README.md # This file
154196
```
155197

@@ -173,10 +215,28 @@ The `getUIExtensionData` method returns:
173215
} | null,
174216
zai: {
175217
hourlyPercentage: number,
176-
weeklyPercentage: number
218+
weeklyPercentage: number,
219+
hourlyNextResetTime?: number,
220+
weeklyNextResetTime?: number
221+
} | null,
222+
neuralwatt: {
223+
isSubscription: boolean,
224+
// Subscription fields
225+
kwhUsed?: number,
226+
kwhIncluded?: number,
227+
kwhPercentage?: number,
228+
currentPeriodEnd?: string,
229+
plan?: string,
230+
inOverage?: boolean,
231+
// Pay-as-you-go fields
232+
creditsRemaining?: number,
233+
creditsTotal?: number,
234+
creditsPercentage?: number,
235+
accountingMethod?: string
177236
} | null,
178237
hasSynthetic: boolean,
179-
hasZai: boolean
238+
hasZai: boolean,
239+
hasNeuralwatt: boolean
180240
}
181241
```
182242

packages/extensions/extensions/providers-quota-extension/StatusBarComponent.jsx

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,76 @@
1111
});
1212
};
1313

14-
return agentProfile?.provider === 'synthetic' && data?.synthetic ? (
15-
data.synthetic.error ? (
14+
if (agentProfile?.provider === 'synthetic' && data?.synthetic) {
15+
return data.synthetic.error ? (
1616
<span className="pt-1">Quota unavailable</span>
1717
) : (
1818
<div className="flex items-center gap-2 pt-1 justify-between w-full">
19-
<span>Synthetic:</span>
19+
<span>Usage:</span>
2020
<div className="flex items-center gap-2">
2121
<span>{data.synthetic.used}/{data.synthetic.limit}</span>
2222
<span>({data.synthetic.percentage}%)</span>
2323
</div>
2424
</div>
25-
)
26-
) : agentProfile?.provider === 'zai-plan' && data?.zai ? (
27-
<div className="flex items-center gap-2 pt-1 justify-between w-full">
28-
<span>Z.ai:</span>
29-
<div className="flex items-center gap-2">
30-
<ui.Tooltip content={data.zai.hourlyNextResetTime ? `Resets at ${formatResetTime(data.zai.hourlyNextResetTime)}` : ''}>
31-
<span>5 Hours: {data.zai.hourlyPercentage}%</span>
32-
</ui.Tooltip>
33-
<span>|</span>
34-
<ui.Tooltip content={data.zai.weeklyNextResetTime ? `Resets at ${formatResetTime(data.zai.weeklyNextResetTime)}` : ''}>
35-
<span>Weekly: {data.zai.weeklyPercentage}%</span>
36-
</ui.Tooltip>
25+
);
26+
}
27+
28+
if (agentProfile?.provider === 'zai-plan' && data?.zai) {
29+
return (
30+
<div className="flex items-center gap-2 pt-1 justify-between w-full">
31+
<span>Usage:</span>
32+
<div className="flex items-center gap-2">
33+
<ui.Tooltip content={data.zai.hourlyNextResetTime ? `Resets at ${formatResetTime(data.zai.hourlyNextResetTime)}` : ''}>
34+
<span>5 Hours: {data.zai.hourlyPercentage}%</span>
35+
</ui.Tooltip>
36+
<span>|</span>
37+
<ui.Tooltip content={data.zai.weeklyNextResetTime ? `Resets at ${formatResetTime(data.zai.weeklyNextResetTime)}` : ''}>
38+
<span>Weekly: {data.zai.weeklyPercentage}%</span>
39+
</ui.Tooltip>
40+
</div>
3741
</div>
38-
</div>
39-
) : null;
42+
);
43+
}
44+
45+
if (agentProfile?.provider === 'neuralwatt' && data?.neuralwatt) {
46+
const nw = data.neuralwatt;
47+
48+
if (nw.isSubscription) {
49+
const kwhUsed = nw.kwhUsed?.toFixed(2) ?? '0.00';
50+
const kwhIncluded = nw.kwhIncluded?.toFixed(1) ?? '0.0';
51+
const periodEnd = nw.currentPeriodEnd ? formatResetTime(nw.currentPeriodEnd) : null;
52+
53+
return (
54+
<div className="flex items-center gap-2 pt-1 justify-between w-full">
55+
<span>Usage:</span>
56+
<div className="flex items-center gap-2">
57+
<ui.Tooltip content={periodEnd ? `Renews at ${periodEnd}` : ''}>
58+
<span>{kwhUsed}/{kwhIncluded} kWh</span>
59+
</ui.Tooltip>
60+
<span>({nw.kwhPercentage}%)</span>
61+
{nw.inOverage && (
62+
<span className="text-red-400 text-xs">overage</span>
63+
)}
64+
</div>
65+
</div>
66+
);
67+
}
68+
69+
const creditsRemaining = nw.creditsRemaining?.toFixed(2) ?? '0.00';
70+
const creditsTotal = nw.creditsTotal?.toFixed(2) ?? '0.00';
71+
72+
return (
73+
<div className="flex items-center gap-2 pt-1 justify-between w-full">
74+
<span>Neuralwatt:</span>
75+
<div className="flex items-center gap-2">
76+
<ui.Tooltip content={`Accounting: ${nw.accountingMethod || 'energy'}`}>
77+
<span>${creditsRemaining}/${creditsTotal}</span>
78+
</ui.Tooltip>
79+
<span>({nw.creditsPercentage}%)</span>
80+
</div>
81+
</div>
82+
);
83+
}
84+
85+
return null;
4086
}

0 commit comments

Comments
 (0)