@kunkun.sh/kuota 0.0.0-stage → 0.1.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 +130 -2
- package/bin/kuota.mjs +3 -0
- package/dist/bin.d.mts +1 -0
- package/dist/bin.mjs +1303 -0
- package/dist/dist-CIjerpSd.mjs +576 -0
- package/dist/history-G4o4HVvW.d.mts +36 -0
- package/dist/history-oOXsjdWR.mjs +236 -0
- package/dist/history.d.mts +3 -0
- package/dist/history.mjs +3 -0
- package/dist/index-2k6FkhpT.d.mts +81 -0
- package/dist/index-NHzh2TGn.d.mts +168 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +7 -0
- package/dist/main-B-hZbKK1.mjs +340 -0
- package/dist/metrics-Bzmrfgn-.mjs +307 -0
- package/dist/metrics-D7oNul_9.d.mts +30 -0
- package/dist/metrics.d.mts +3 -0
- package/dist/metrics.mjs +3 -0
- package/dist/parsers.d.mts +13 -0
- package/dist/parsers.mjs +19 -0
- package/dist/providers.d.mts +2 -0
- package/dist/providers.mjs +1 -0
- package/dist/src-C48Ew_L9.mjs +707 -0
- package/dist/src-y_QKmTyj.mjs +309 -0
- package/dist/web/assets/index-ihoe7C_u.js +27 -0
- package/dist/web/index.html +30 -0
- package/dist/web-server-DkdA5Ixj.mjs +154 -0
- package/package.json +73 -4
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Kuota · AI Quota & Usage Dashboard</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<script>
|
|
9
|
+
tailwind.config = {
|
|
10
|
+
darkMode: 'class',
|
|
11
|
+
theme: {
|
|
12
|
+
extend: {
|
|
13
|
+
colors: {
|
|
14
|
+
background: '#09090b',
|
|
15
|
+
card: '#111113',
|
|
16
|
+
border: '#27272a',
|
|
17
|
+
foreground: '#fafafa',
|
|
18
|
+
muted: '#a1a1aa'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
<style>body{color:#fafafa;background-color:#09090b;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,SF Pro Display,SF Pro Text,Segoe UI,Roboto,Helvetica,Arial,sans-serif}</style>
|
|
25
|
+
<script type="module" crossorigin src="/assets/index-ihoe7C_u.js"></script>
|
|
26
|
+
</head>
|
|
27
|
+
<body class="bg-[#09090b] text-zinc-100 min-h-screen antialiased selection:bg-zinc-800">
|
|
28
|
+
<div id="root"></div>
|
|
29
|
+
</body>
|
|
30
|
+
</html>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { i as readAll, n as builtInProviders, t as PROVIDER_METADATA } from "./bin.mjs";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
4
|
+
import { readFile, stat } from "node:fs/promises";
|
|
5
|
+
import { dirname, extname, join } from "node:path";
|
|
6
|
+
import { createServer } from "node:http";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
// ../cli/src/web-server.ts
|
|
9
|
+
const MIME_TYPES = {
|
|
10
|
+
".html": "text/html; charset=utf-8",
|
|
11
|
+
".js": "application/javascript; charset=utf-8",
|
|
12
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
13
|
+
".css": "text/css; charset=utf-8",
|
|
14
|
+
".json": "application/json; charset=utf-8",
|
|
15
|
+
".png": "image/png",
|
|
16
|
+
".jpg": "image/jpeg",
|
|
17
|
+
".jpeg": "image/jpeg",
|
|
18
|
+
".gif": "image/gif",
|
|
19
|
+
".svg": "image/svg+xml",
|
|
20
|
+
".ico": "image/x-icon",
|
|
21
|
+
".woff": "font/woff",
|
|
22
|
+
".woff2": "font/woff2",
|
|
23
|
+
".ttf": "font/ttf"
|
|
24
|
+
};
|
|
25
|
+
async function findWebDir() {
|
|
26
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const candidates = [
|
|
28
|
+
join(currentDir, "web"),
|
|
29
|
+
join(currentDir, "..", "..", "kunkun", "dist"),
|
|
30
|
+
join(process.cwd(), "packages", "kunkun", "dist"),
|
|
31
|
+
join(process.cwd(), "dist", "web")
|
|
32
|
+
];
|
|
33
|
+
for (const candidate of candidates) try {
|
|
34
|
+
if ((await stat(candidate)).isDirectory()) {
|
|
35
|
+
const indexFile = join(candidate, "index.html");
|
|
36
|
+
if ((await stat(indexFile)).isFile()) return candidate;
|
|
37
|
+
}
|
|
38
|
+
} catch {}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function openBrowser(url) {
|
|
42
|
+
try {
|
|
43
|
+
if (process.platform === "darwin") execFile("open", [url], () => {});
|
|
44
|
+
else if (process.platform === "win32") execFile("cmd", [
|
|
45
|
+
"/c",
|
|
46
|
+
"start",
|
|
47
|
+
url
|
|
48
|
+
], () => {});
|
|
49
|
+
else execFile("xdg-open", [url], () => {});
|
|
50
|
+
} catch {}
|
|
51
|
+
}
|
|
52
|
+
async function startWebServer(options = {}, output = {
|
|
53
|
+
writeStdout: (m) => process.stdout.write(`${m}\n`),
|
|
54
|
+
writeStderr: (m) => process.stderr.write(`${m}\n`)
|
|
55
|
+
}, providers = builtInProviders()) {
|
|
56
|
+
const port = options.port ?? 5173;
|
|
57
|
+
const host = options.host ?? "127.0.0.1";
|
|
58
|
+
const shouldOpen = options.open ?? true;
|
|
59
|
+
const webDir = await findWebDir();
|
|
60
|
+
const server = createServer(async (req, res) => {
|
|
61
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
62
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
63
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
64
|
+
if (req.method === "OPTIONS") {
|
|
65
|
+
res.writeHead(204);
|
|
66
|
+
res.end();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const pathname = new URL(req.url ?? "/", `http://${req.headers.host || "localhost"}`).pathname;
|
|
70
|
+
if (pathname === "/api/health") {
|
|
71
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
72
|
+
res.end(JSON.stringify({
|
|
73
|
+
status: "ok",
|
|
74
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
75
|
+
}));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (pathname === "/api/status") {
|
|
79
|
+
try {
|
|
80
|
+
const ids = PROVIDER_METADATA.map((item) => item.id);
|
|
81
|
+
const snapshots = await Effect.runPromise(readAll(ids, providers));
|
|
82
|
+
const envelope = {
|
|
83
|
+
schemaVersion: 1,
|
|
84
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
85
|
+
providers: snapshots,
|
|
86
|
+
errors: []
|
|
87
|
+
};
|
|
88
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
89
|
+
res.end(JSON.stringify(envelope));
|
|
90
|
+
} catch (err) {
|
|
91
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
92
|
+
res.end(JSON.stringify({ error: String(err) }));
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (webDir) {
|
|
97
|
+
let filePath = join(webDir, pathname === "/" ? "/index.html" : pathname);
|
|
98
|
+
try {
|
|
99
|
+
let fileStat = await stat(filePath).catch(() => null);
|
|
100
|
+
if (!fileStat || fileStat.isDirectory()) {
|
|
101
|
+
filePath = join(webDir, "index.html");
|
|
102
|
+
fileStat = await stat(filePath).catch(() => null);
|
|
103
|
+
}
|
|
104
|
+
if (fileStat && fileStat.isFile()) {
|
|
105
|
+
const ext = extname(filePath).toLowerCase();
|
|
106
|
+
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
107
|
+
const data = await readFile(filePath);
|
|
108
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
109
|
+
res.end(data);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
} catch {}
|
|
113
|
+
}
|
|
114
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
115
|
+
res.end(`
|
|
116
|
+
<!DOCTYPE html>
|
|
117
|
+
<html>
|
|
118
|
+
<head>
|
|
119
|
+
<title>Kuota Web Workbench</title>
|
|
120
|
+
<style>
|
|
121
|
+
body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; background: #09090b; color: #f4f4f5; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
|
|
122
|
+
.card { background: #18181b; border: 1px solid #27272a; border-radius: 12px; padding: 32px; max-width: 480px; text-align: center; }
|
|
123
|
+
h1 { font-size: 20px; margin-bottom: 8px; color: #fff; }
|
|
124
|
+
p { font-size: 14px; color: #a1a1aa; line-height: 1.5; }
|
|
125
|
+
code { background: #27272a; padding: 2px 6px; border-radius: 4px; font-size: 12px; color: #38bdf8; }
|
|
126
|
+
</style>
|
|
127
|
+
</head>
|
|
128
|
+
<body>
|
|
129
|
+
<div class="card">
|
|
130
|
+
<h1>Kuota Web Workbench</h1>
|
|
131
|
+
<p>Static bundle was not detected beside the CLI binary.</p>
|
|
132
|
+
<p>API endpoint is active at <code>/api/status</code>.</p>
|
|
133
|
+
</div>
|
|
134
|
+
</body>
|
|
135
|
+
</html>
|
|
136
|
+
`);
|
|
137
|
+
});
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
server.listen(port, host, () => {
|
|
140
|
+
const serverUrl = `http://${host}:${port}`;
|
|
141
|
+
output.writeStdout(`\n ⚡ Kuota Web Workbench running at: ${serverUrl}`);
|
|
142
|
+
output.writeStdout(` Press Ctrl+C to stop.\n`);
|
|
143
|
+
if (shouldOpen) openBrowser(serverUrl);
|
|
144
|
+
});
|
|
145
|
+
const shutdown = () => {
|
|
146
|
+
server.close(() => {
|
|
147
|
+
resolve();
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
process.on("SIGINT", shutdown);
|
|
151
|
+
process.on("SIGTERM", shutdown);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
export { startWebServer };
|
package/package.json
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kunkun.sh/kuota",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Truthful multi-provider AI quota monitoring, forecasting, and parsing library & CLI suite (OpenAI Codex, Claude Code, Google Antigravity)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Huakun Shen",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.mjs",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"bin": {
|
|
12
|
+
"kuota": "bin/kuota.mjs"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs"
|
|
18
|
+
},
|
|
19
|
+
"./parsers": {
|
|
20
|
+
"types": "./dist/parsers.d.ts",
|
|
21
|
+
"import": "./dist/parsers.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./metrics": {
|
|
24
|
+
"types": "./dist/metrics.d.ts",
|
|
25
|
+
"import": "./dist/metrics.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./history": {
|
|
28
|
+
"types": "./dist/history.d.ts",
|
|
29
|
+
"import": "./dist/history.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./providers": {
|
|
32
|
+
"types": "./dist/providers.d.ts",
|
|
33
|
+
"import": "./dist/providers.mjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"bin",
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/HuakunShen/kuota.git"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"ai",
|
|
54
|
+
"quota",
|
|
55
|
+
"usage",
|
|
56
|
+
"parser",
|
|
57
|
+
"codex",
|
|
58
|
+
"claude",
|
|
59
|
+
"antigravity",
|
|
60
|
+
"tui",
|
|
61
|
+
"dashboard",
|
|
62
|
+
"pace",
|
|
63
|
+
"forecast",
|
|
64
|
+
"kunkun"
|
|
65
|
+
],
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@effect/cli": "^0.77.2",
|
|
68
|
+
"@effect/platform-node": "^0.108.0",
|
|
69
|
+
"@uniview/tui-core": "^0.0.3",
|
|
70
|
+
"@uniview/tui-react": "^0.0.3",
|
|
71
|
+
"effect": "^3.22.4",
|
|
72
|
+
"react": "^19.2.0"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {}
|
|
75
|
+
}
|