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 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
@@ -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
+ }