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.
Files changed (3) hide show
  1. package/README.md +19 -0
  2. package/dist/index.js +118 -0
  3. 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
+ }