opencode-crof-sidebar 0.1.1
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/README.md +19 -0
- package/dist/index.js +118 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# opencode-crof-sidebar
|
|
2
|
+
|
|
3
|
+
OpenCode TUI plugin that displays CrofAI usage (requests/day, credits) in the sidebar.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
opencode plugin opencode-crof-sidebar
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Shows CrofAI usage information in the sidebar when using a CrofAI model
|
|
14
|
+
- Displays remaining requests per day and credits
|
|
15
|
+
- Auto-refreshes every 30 seconds
|
|
16
|
+
|
|
17
|
+
## Credits
|
|
18
|
+
|
|
19
|
+
Nahcrof, Red44
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/index.ts
|
|
3
|
+
import { createElement, createTextNode, insert } from "@opentui/solid";
|
|
4
|
+
import { createSignal } from "solid-js";
|
|
5
|
+
var CROFAI_USAGE_URL = "https://crof.ai/usage_api/";
|
|
6
|
+
function getCrofaiKey(api) {
|
|
7
|
+
const provider = api.state.provider.find((p) => p.name === "CrofAI");
|
|
8
|
+
const fromConfig = provider?.options?.apiKey;
|
|
9
|
+
if (fromConfig)
|
|
10
|
+
return fromConfig;
|
|
11
|
+
if (provider?.key)
|
|
12
|
+
return provider.key;
|
|
13
|
+
return process.env.CROFAI_API_KEY;
|
|
14
|
+
}
|
|
15
|
+
function getCrofaiProviderID(api) {
|
|
16
|
+
return api.state.provider.find((p) => p.name === "CrofAI")?.id;
|
|
17
|
+
}
|
|
18
|
+
function isCrofaiSession(api, sessionID, crofaiProviderID) {
|
|
19
|
+
const messages = api.state.session.messages(sessionID);
|
|
20
|
+
for (let i = messages.length - 1;i >= 0; i -= 1) {
|
|
21
|
+
const message = messages[i];
|
|
22
|
+
if (message.role === "assistant") {
|
|
23
|
+
return message.providerID === crofaiProviderID;
|
|
24
|
+
}
|
|
25
|
+
if (message.role === "user") {
|
|
26
|
+
return message.model.providerID === crofaiProviderID;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
async function fetchUsage(key) {
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetch(CROFAI_USAGE_URL, {
|
|
34
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
return null;
|
|
38
|
+
return await res.json();
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function buildSidebar(api, d, err) {
|
|
44
|
+
const t = api.theme.current;
|
|
45
|
+
const root = createElement("box", {
|
|
46
|
+
border: true,
|
|
47
|
+
borderColor: t.border,
|
|
48
|
+
backgroundColor: t.backgroundPanel,
|
|
49
|
+
paddingTop: 1,
|
|
50
|
+
paddingBottom: 1,
|
|
51
|
+
paddingLeft: 2,
|
|
52
|
+
paddingRight: 2,
|
|
53
|
+
flexDirection: "column",
|
|
54
|
+
gap: 1
|
|
55
|
+
});
|
|
56
|
+
const title = createElement("text", { fg: t.primary });
|
|
57
|
+
insert(title, createTextNode("CrofAI"));
|
|
58
|
+
insert(root, title);
|
|
59
|
+
if (err) {
|
|
60
|
+
const errText = createElement("text", { fg: t.error });
|
|
61
|
+
insert(errText, createTextNode("Failed to fetch usage"));
|
|
62
|
+
insert(root, errText);
|
|
63
|
+
} else if (!d) {
|
|
64
|
+
const loadingText = createElement("text", { fg: t.textMuted });
|
|
65
|
+
insert(loadingText, createTextNode("Loading..."));
|
|
66
|
+
insert(root, loadingText);
|
|
67
|
+
} else {
|
|
68
|
+
if (d.usable_requests !== null) {
|
|
69
|
+
const reqLine = createElement("text", { fg: t.text });
|
|
70
|
+
insert(reqLine, createTextNode("Requests: " + d.usable_requests + "/day"));
|
|
71
|
+
insert(root, reqLine);
|
|
72
|
+
} else {
|
|
73
|
+
const planText = createElement("text", { fg: t.text });
|
|
74
|
+
insert(planText, createTextNode("Pay-per-token"));
|
|
75
|
+
insert(root, planText);
|
|
76
|
+
}
|
|
77
|
+
const credLine = createElement("text", { fg: t.text });
|
|
78
|
+
insert(credLine, createTextNode("Credits: $" + d.credits.toFixed(4)));
|
|
79
|
+
insert(root, credLine);
|
|
80
|
+
}
|
|
81
|
+
return root;
|
|
82
|
+
}
|
|
83
|
+
var tui = async (api) => {
|
|
84
|
+
const key = getCrofaiKey(api);
|
|
85
|
+
const crofaiProviderID = getCrofaiProviderID(api);
|
|
86
|
+
if (!key || !crofaiProviderID)
|
|
87
|
+
return;
|
|
88
|
+
const [getData, setData] = createSignal(null);
|
|
89
|
+
const [getErr, setErr] = createSignal(false);
|
|
90
|
+
const refresh = async () => {
|
|
91
|
+
const result = await fetchUsage(key);
|
|
92
|
+
if (result) {
|
|
93
|
+
setData(result);
|
|
94
|
+
setErr(false);
|
|
95
|
+
} else {
|
|
96
|
+
setErr(true);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
await refresh();
|
|
100
|
+
const usageInterval = setInterval(refresh, 30000);
|
|
101
|
+
api.lifecycle.onDispose(() => {
|
|
102
|
+
clearInterval(usageInterval);
|
|
103
|
+
});
|
|
104
|
+
api.slots.register({
|
|
105
|
+
order: 150,
|
|
106
|
+
slots: {
|
|
107
|
+
sidebar_content(_ctx, props) {
|
|
108
|
+
if (!isCrofaiSession(api, props.session_id, crofaiProviderID))
|
|
109
|
+
return null;
|
|
110
|
+
return buildSidebar(api, getData(), getErr());
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
var src_default = tui;
|
|
116
|
+
export {
|
|
117
|
+
src_default as default
|
|
118
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-crof-sidebar",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "OpenCode TUI plugin that displays CrofAI usage (requests/day, credits) in the sidebar",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./tui": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"clean": "rm -rf dist && mkdir dist",
|
|
22
|
+
"build": "bun run clean && bun build src/index.ts --outdir dist --target=bun --external @opencode-ai/plugin --external @opencode-ai/plugin/tui --external @opentui/core --external @opentui/solid --external solid-js"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@opencode-ai/plugin": "*",
|
|
26
|
+
"@opentui/core": ">=0.1.96",
|
|
27
|
+
"@opentui/solid": ">=0.1.96",
|
|
28
|
+
"solid-js": ">=1.7.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependenciesMeta": {
|
|
31
|
+
"@opencode-ai/plugin": { "optional": true },
|
|
32
|
+
"@opentui/core": { "optional": true },
|
|
33
|
+
"@opentui/solid": { "optional": true },
|
|
34
|
+
"solid-js": { "optional": true }
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/Red44/crofai-opencode.git"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"opencode",
|
|
42
|
+
"opencode-plugin",
|
|
43
|
+
"crofai",
|
|
44
|
+
"tui",
|
|
45
|
+
"sidebar"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"author": "Nahcrof, Red44",
|
|
49
|
+
"engines": {
|
|
50
|
+
"opencode": ">=1.4.0"
|
|
51
|
+
}
|
|
52
|
+
}
|