opencode-firmware-quota 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alan Garcia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# opencode-firmware-quota
|
|
2
|
+
|
|
3
|
+
OpenCode plugin for monitoring your [Firmware](https://firmware.ai) API quota usage.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **`firmware_quota` tool** - AI can check your quota on demand
|
|
8
|
+
- **`/usage` command** - Quick quota check via slash command
|
|
9
|
+
- **Auto-show on session start** - See your quota when starting a new session
|
|
10
|
+
- **Low quota warnings** - Get notified when usage exceeds 75% or 90%
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Add to your `opencode.json`:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"plugin": ["opencode-firmware-quota"]
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
Connect your Firmware account using the `/connect` command in OpenCode:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
/connect
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Search for **Firmware** and enter your API key from [app.firmware.ai](https://app.firmware.ai).
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Slash Command
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/usage
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Shows a toast notification with your current quota usage.
|
|
41
|
+
|
|
42
|
+
### AI Tool
|
|
43
|
+
|
|
44
|
+
Ask the AI to check your quota:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Check my Firmware quota
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Automatic Notifications
|
|
51
|
+
|
|
52
|
+
- **Session start**: Quota is displayed when you start a new session
|
|
53
|
+
- **Low quota (75%+)**: Warning notification shown
|
|
54
|
+
- **Critical quota (90%+)**: Error notification shown
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
The plugin reads your Firmware API key from:
|
|
59
|
+
|
|
60
|
+
1. `FIRMWARE_API_KEY` environment variable (if set)
|
|
61
|
+
2. OpenCode auth storage (`~/.local/share/opencode/auth.json`)
|
|
62
|
+
|
|
63
|
+
No additional configuration is required if you've connected Firmware via `/connect`.
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
|
+
/**
|
|
3
|
+
* OpenCode plugin for Firmware API quota monitoring
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - firmware_quota tool: Check quota on demand
|
|
7
|
+
* - /usage command: Quick quota check via slash command
|
|
8
|
+
* - Auto-show quota on session start
|
|
9
|
+
* - Low quota warnings when usage exceeds thresholds
|
|
10
|
+
*/
|
|
11
|
+
export declare const FirmwareQuotaPlugin: Plugin;
|
|
12
|
+
export default FirmwareQuotaPlugin;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAkGjD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAsHjC,CAAA;AAGD,eAAe,mBAAmB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
// Configuration
|
|
5
|
+
const LOW_QUOTA_THRESHOLD = 75; // Show warning at 75%
|
|
6
|
+
const CRITICAL_QUOTA_THRESHOLD = 90; // Show critical warning at 90%
|
|
7
|
+
/**
|
|
8
|
+
* Get the Firmware API key from environment or OpenCode auth storage
|
|
9
|
+
*/
|
|
10
|
+
function getFirmwareApiKey() {
|
|
11
|
+
// Try environment variable first
|
|
12
|
+
if (process.env.FIRMWARE_API_KEY) {
|
|
13
|
+
return process.env.FIRMWARE_API_KEY;
|
|
14
|
+
}
|
|
15
|
+
// Fall back to OpenCode auth storage
|
|
16
|
+
const authPath = join(homedir(), ".local", "share", "opencode", "auth.json");
|
|
17
|
+
try {
|
|
18
|
+
const auth = JSON.parse(readFileSync(authPath, "utf-8"));
|
|
19
|
+
if (auth.firmware?.key) {
|
|
20
|
+
return auth.firmware.key;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// File doesn't exist or is invalid
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fetch quota information from Firmware API
|
|
30
|
+
*/
|
|
31
|
+
async function fetchQuota(apiKey) {
|
|
32
|
+
const response = await fetch("https://app.firmware.ai/api/v1/quota", {
|
|
33
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new Error(`API returned ${response.status}`);
|
|
37
|
+
}
|
|
38
|
+
return response.json();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse quota response into usable info
|
|
42
|
+
*/
|
|
43
|
+
function parseQuotaInfo(data) {
|
|
44
|
+
const usedPercent = Math.round(data.used * 100);
|
|
45
|
+
let resetTime = null;
|
|
46
|
+
if (data.reset) {
|
|
47
|
+
const resetDate = new Date(data.reset);
|
|
48
|
+
resetTime = resetDate.toLocaleTimeString([], {
|
|
49
|
+
hour: "2-digit",
|
|
50
|
+
minute: "2-digit",
|
|
51
|
+
timeZoneName: "short",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
usedPercent,
|
|
56
|
+
resetTime,
|
|
57
|
+
isLow: usedPercent >= LOW_QUOTA_THRESHOLD,
|
|
58
|
+
isCritical: usedPercent >= CRITICAL_QUOTA_THRESHOLD,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format quota info as a display message
|
|
63
|
+
*/
|
|
64
|
+
function formatQuotaMessage(info) {
|
|
65
|
+
const resetPart = info.resetTime ? `Resets at ${info.resetTime}` : "No active window";
|
|
66
|
+
if (info.isCritical) {
|
|
67
|
+
return `Firmware: ${info.usedPercent}% used (CRITICAL) | ${resetPart}`;
|
|
68
|
+
}
|
|
69
|
+
else if (info.isLow) {
|
|
70
|
+
return `Firmware: ${info.usedPercent}% used (LOW) | ${resetPart}`;
|
|
71
|
+
}
|
|
72
|
+
return `Firmware: ${info.usedPercent}% used | ${resetPart}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* OpenCode plugin for Firmware API quota monitoring
|
|
76
|
+
*
|
|
77
|
+
* Features:
|
|
78
|
+
* - firmware_quota tool: Check quota on demand
|
|
79
|
+
* - /usage command: Quick quota check via slash command
|
|
80
|
+
* - Auto-show quota on session start
|
|
81
|
+
* - Low quota warnings when usage exceeds thresholds
|
|
82
|
+
*/
|
|
83
|
+
export const FirmwareQuotaPlugin = async ({ client }) => {
|
|
84
|
+
/**
|
|
85
|
+
* Core function to check and display quota
|
|
86
|
+
*/
|
|
87
|
+
async function checkQuota(options = {}) {
|
|
88
|
+
const { showToast = true, silent = false } = options;
|
|
89
|
+
const apiKey = getFirmwareApiKey();
|
|
90
|
+
if (!apiKey) {
|
|
91
|
+
const errorMsg = "Firmware API key not found. Run /connect and add your Firmware credentials.";
|
|
92
|
+
if (showToast && !silent) {
|
|
93
|
+
await client.tui.showToast({
|
|
94
|
+
body: { message: "Firmware not connected. Run /connect", variant: "error" },
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return `Error: ${errorMsg}`;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const data = await fetchQuota(apiKey);
|
|
101
|
+
const info = parseQuotaInfo(data);
|
|
102
|
+
const message = formatQuotaMessage(info);
|
|
103
|
+
if (showToast) {
|
|
104
|
+
const variant = info.isCritical ? "error" : info.isLow ? "warning" : "info";
|
|
105
|
+
await client.tui.showToast({
|
|
106
|
+
body: { message, variant },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return message;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const error = err;
|
|
113
|
+
const errorMsg = `Quota fetch failed: ${error.message}`;
|
|
114
|
+
if (showToast && !silent) {
|
|
115
|
+
await client.tui.showToast({
|
|
116
|
+
body: { message: errorMsg, variant: "error" },
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return `Error: ${errorMsg}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if Firmware is connected (has API key)
|
|
124
|
+
*/
|
|
125
|
+
function isFirmwareConnected() {
|
|
126
|
+
return getFirmwareApiKey() !== null;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
// Tool: firmware_quota - Check quota on demand via AI tool call
|
|
130
|
+
tool: {
|
|
131
|
+
firmware_quota: {
|
|
132
|
+
description: "Check your Firmware API quota usage",
|
|
133
|
+
args: {},
|
|
134
|
+
async execute() {
|
|
135
|
+
return checkQuota();
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
// Command: /usage - Quick quota check via slash command
|
|
140
|
+
command: {
|
|
141
|
+
usage: {
|
|
142
|
+
description: "Check your Firmware API quota usage",
|
|
143
|
+
async execute() {
|
|
144
|
+
await checkQuota();
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
// Event handlers
|
|
149
|
+
event: async ({ event }) => {
|
|
150
|
+
// Auto-show quota on session start (only if Firmware is connected)
|
|
151
|
+
if (event.type === "session.created") {
|
|
152
|
+
if (isFirmwareConnected()) {
|
|
153
|
+
// Small delay to let the UI settle
|
|
154
|
+
setTimeout(async () => {
|
|
155
|
+
await checkQuota({ showToast: true });
|
|
156
|
+
}, 500);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Low quota warning when session becomes idle (after AI response)
|
|
160
|
+
// This is a good time to check quota without being too intrusive
|
|
161
|
+
if (event.type === "session.idle") {
|
|
162
|
+
if (isFirmwareConnected()) {
|
|
163
|
+
try {
|
|
164
|
+
const apiKey = getFirmwareApiKey();
|
|
165
|
+
if (apiKey) {
|
|
166
|
+
const data = await fetchQuota(apiKey);
|
|
167
|
+
const info = parseQuotaInfo(data);
|
|
168
|
+
// Only show warning if quota is low/critical
|
|
169
|
+
if (info.isCritical) {
|
|
170
|
+
await client.tui.showToast({
|
|
171
|
+
body: {
|
|
172
|
+
message: `Warning: Firmware quota at ${info.usedPercent}%!`,
|
|
173
|
+
variant: "error",
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else if (info.isLow) {
|
|
178
|
+
await client.tui.showToast({
|
|
179
|
+
body: {
|
|
180
|
+
message: `Notice: Firmware quota at ${info.usedPercent}%`,
|
|
181
|
+
variant: "warning",
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Silently ignore errors during background checks
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
// Default export for convenience
|
|
196
|
+
export default FirmwareQuotaPlugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-firmware-quota",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenCode plugin for Firmware API quota monitoring - check usage, get warnings, and track your Firmware API consumption",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"opencode",
|
|
17
|
+
"opencode-plugin",
|
|
18
|
+
"firmware",
|
|
19
|
+
"firmware-ai",
|
|
20
|
+
"llm",
|
|
21
|
+
"quota",
|
|
22
|
+
"usage"
|
|
23
|
+
],
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/your-username/opencode-firmware-quota"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@opencode-ai/plugin": "^1.0.0",
|
|
32
|
+
"@types/node": "^25.0.10",
|
|
33
|
+
"typescript": "^5.0.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@opencode-ai/plugin": "^1.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|