@emesoft/tokenhub 0.5.0 → 0.6.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/README.md +6 -4
- package/bin/tokenhub.js +7 -10
- package/lib/pair.d.ts +3 -1
- package/lib/pair.js +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Pair Claude Code on this machine with a [TokenHub](https://tokenhub.aimpact.io.vn) pool. No dependencies, Node 18+.
|
|
4
4
|
|
|
5
|
+
`connect` pairs with https://tokenhub.aimpact.io.vn by default. For another pool, pass its address: `npx @emesoft/tokenhub connect https://pool.example.com`.
|
|
6
|
+
|
|
5
7
|
```
|
|
6
|
-
npx @emesoft/tokenhub connect
|
|
7
|
-
npx @emesoft/tokenhub connect
|
|
8
|
+
npx @emesoft/tokenhub connect
|
|
9
|
+
npx @emesoft/tokenhub connect --no-statusline
|
|
8
10
|
npx @emesoft/tokenhub usage
|
|
9
11
|
npx @emesoft/tokenhub dashboard
|
|
10
12
|
npx @emesoft/tokenhub disconnect
|
|
11
|
-
npx @emesoft/tokenhub connect
|
|
13
|
+
npx @emesoft/tokenhub connect --admin
|
|
12
14
|
npx @emesoft/tokenhub disconnect --admin
|
|
13
15
|
```
|
|
14
16
|
|
|
@@ -26,4 +28,4 @@ Requests to the pool carry your key and one extra header, `x-tokenhub-cli: <vers
|
|
|
26
28
|
|
|
27
29
|
If `ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` is set in your shell, it overrides `settings.json`.
|
|
28
30
|
|
|
29
|
-
Sign in, manage your keys and top up at [tokenhub.aimpact.io.vn](https://tokenhub.aimpact.io.vn).
|
|
31
|
+
Sign in, manage your keys and top up at [tokenhub.aimpact.io.vn](https://tokenhub.aimpact.io.vn).
|
package/bin/tokenhub.js
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { adminConfigPath, removeAdminConfig } from "../lib/admin.js";
|
|
4
4
|
import { parseDashboardArgs, runDashboard } from "../lib/dashboard.js";
|
|
5
|
-
import { runConnect } from "../lib/pair.js";
|
|
5
|
+
import { DEFAULT_POOL_URL, runConnect } from "../lib/pair.js";
|
|
6
6
|
import { disconnectSettings, readSettings, settingsPath } from "../lib/settings.js";
|
|
7
7
|
import { fetchUsage, formatUsage, resolveCredentials } from "../lib/usage.js";
|
|
8
8
|
|
|
9
9
|
const HELP = `tokenhub - pair Claude Code with a TokenHub pool
|
|
10
10
|
|
|
11
11
|
Usage:
|
|
12
|
-
tokenhub connect
|
|
12
|
+
tokenhub connect [poolUrl] [--no-statusline]
|
|
13
13
|
Pair this machine and write ~/.claude/settings.json, including the status line
|
|
14
|
-
(today's spend under the prompt) unless --no-statusline
|
|
15
|
-
|
|
14
|
+
(today's spend under the prompt) unless --no-statusline.
|
|
15
|
+
poolUrl defaults to ${DEFAULT_POOL_URL}
|
|
16
|
+
tokenhub connect [poolUrl] --admin
|
|
16
17
|
Pair this machine as an admin device (for the desktop overlay's pool view): the admin
|
|
17
18
|
confirms in the console, the token is saved to ~/.tokenhub/admin.json
|
|
18
19
|
tokenhub usage [--json] Show today's and this week's spend, credit and pool health
|
|
@@ -43,10 +44,6 @@ async function main(argv) {
|
|
|
43
44
|
}
|
|
44
45
|
const file = settingsPath();
|
|
45
46
|
if (command === "connect") {
|
|
46
|
-
if (!arg) {
|
|
47
|
-
console.error(`Missing pool URL.\n\n${HELP}`);
|
|
48
|
-
return 1;
|
|
49
|
-
}
|
|
50
47
|
const controller = new AbortController();
|
|
51
48
|
process.once("SIGINT", () => controller.abort());
|
|
52
49
|
return runConnect({
|
|
@@ -62,7 +59,7 @@ async function main(argv) {
|
|
|
62
59
|
try {
|
|
63
60
|
const credentials = resolveCredentials(readSettings(file).settings);
|
|
64
61
|
if (!credentials) {
|
|
65
|
-
console.error("Not connected. Run `tokenhub connect
|
|
62
|
+
console.error("Not connected. Run `tokenhub connect` first.");
|
|
66
63
|
return 1;
|
|
67
64
|
}
|
|
68
65
|
const report = await fetchUsage(credentials.baseUrl, credentials.key);
|
|
@@ -78,7 +75,7 @@ async function main(argv) {
|
|
|
78
75
|
const options = parseDashboardArgs(argv.slice(1));
|
|
79
76
|
const credentials = resolveCredentials(readSettings(file).settings);
|
|
80
77
|
if (!credentials) {
|
|
81
|
-
console.error("Not connected. Run `tokenhub connect
|
|
78
|
+
console.error("Not connected. Run `tokenhub connect` first.");
|
|
82
79
|
return 1;
|
|
83
80
|
}
|
|
84
81
|
return await runDashboard(credentials, options);
|
package/lib/pair.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export const DEFAULT_POOL_URL: string;
|
|
1
2
|
export function openBrowser(url: string, platform?: string): void;
|
|
2
3
|
export function runConnect(options: {
|
|
3
|
-
|
|
4
|
+
/** Pool address; defaults to `DEFAULT_POOL_URL`. */
|
|
5
|
+
poolUrl?: string;
|
|
4
6
|
settingsFile: string;
|
|
5
7
|
log?: (line: string) => void;
|
|
6
8
|
open?: (url: string) => void;
|
package/lib/pair.js
CHANGED
|
@@ -5,6 +5,9 @@ import { connectSettings, normalizeUrl, overridingEnvVars, readSettings } from "
|
|
|
5
5
|
|
|
6
6
|
const MAX_WAIT_MS = 15 * 60 * 1000;
|
|
7
7
|
|
|
8
|
+
/** The pool `connect` pairs with when no address is given. */
|
|
9
|
+
export const DEFAULT_POOL_URL = "https://tokenhub.aimpact.io.vn";
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Open a URL in the default browser; failures are ignored (the URL is printed anyway).
|
|
10
13
|
* @param {string} url Address to open.
|
|
@@ -62,7 +65,7 @@ async function postJson(url, body, signal) {
|
|
|
62
65
|
/**
|
|
63
66
|
* Run the pairing flow and write the issued key into settings.json.
|
|
64
67
|
* @param {object} options
|
|
65
|
-
* @param {string} options.poolUrl Pool address as typed by the user.
|
|
68
|
+
* @param {string} [options.poolUrl] Pool address as typed by the user (default `DEFAULT_POOL_URL`).
|
|
66
69
|
* @param {string} options.settingsFile Path of settings.json to update.
|
|
67
70
|
* @param {(line: string) => void} [options.log] Output sink.
|
|
68
71
|
* @param {(url: string) => void} [options.open] Browser opener.
|
|
@@ -76,7 +79,7 @@ async function postJson(url, body, signal) {
|
|
|
76
79
|
* @returns {Promise<number>} Process exit code.
|
|
77
80
|
*/
|
|
78
81
|
export async function runConnect({
|
|
79
|
-
poolUrl,
|
|
82
|
+
poolUrl = DEFAULT_POOL_URL,
|
|
80
83
|
settingsFile,
|
|
81
84
|
log = console.log,
|
|
82
85
|
open = openBrowser,
|