useclaudeproxy 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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/app.d.ts +2 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +47 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/args.d.ts +17 -0
  8. package/dist/args.d.ts.map +1 -0
  9. package/dist/args.js +37 -0
  10. package/dist/args.js.map +1 -0
  11. package/dist/config-yaml.d.ts +5 -0
  12. package/dist/config-yaml.d.ts.map +1 -0
  13. package/dist/config-yaml.js +26 -0
  14. package/dist/config-yaml.js.map +1 -0
  15. package/dist/config.d.ts +9 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +29 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/http-client.d.ts +10 -0
  20. package/dist/http-client.d.ts.map +1 -0
  21. package/dist/http-client.js +33 -0
  22. package/dist/http-client.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +27 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/install-cli-proxy.d.ts +2 -0
  28. package/dist/install-cli-proxy.d.ts.map +1 -0
  29. package/dist/install-cli-proxy.js +140 -0
  30. package/dist/install-cli-proxy.js.map +1 -0
  31. package/dist/providers/hermes.d.ts +15 -0
  32. package/dist/providers/hermes.d.ts.map +1 -0
  33. package/dist/providers/hermes.js +210 -0
  34. package/dist/providers/hermes.js.map +1 -0
  35. package/dist/providers/index.d.ts +5 -0
  36. package/dist/providers/index.d.ts.map +1 -0
  37. package/dist/providers/index.js +11 -0
  38. package/dist/providers/index.js.map +1 -0
  39. package/dist/providers/types.d.ts +7 -0
  40. package/dist/providers/types.d.ts.map +1 -0
  41. package/dist/providers/types.js +2 -0
  42. package/dist/providers/types.js.map +1 -0
  43. package/dist/run-cli-proxy.d.ts +2 -0
  44. package/dist/run-cli-proxy.d.ts.map +1 -0
  45. package/dist/run-cli-proxy.js +22 -0
  46. package/dist/run-cli-proxy.js.map +1 -0
  47. package/dist/types.d.ts +31 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +23 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/yaml.example.d.ts +2 -0
  52. package/dist/yaml.example.d.ts.map +1 -0
  53. package/dist/yaml.example.js +141 -0
  54. package/dist/yaml.example.js.map +1 -0
  55. package/package.json +96 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Meisam Maani
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,120 @@
1
+ # useclaudeproxy
2
+
3
+ A TypeScript CLI (`useclaudeproxy`) that authenticates the **Hermes CLI** against
4
+ [Nous Research](https://nousresearch.com) via OAuth 2.0 Device Authorization
5
+ Grant, then downloads, configures, and runs
6
+ [`CLIProxyAPI`](https://github.com/router-for-me/CLIProxyAPI) — a local
7
+ OpenAI / Gemini / Claude / Codex compatible proxy — wired with the token it
8
+ just obtained.
9
+
10
+ In short: run one command, complete the device-flow login in your browser, and
11
+ you get a local proxy endpoint that Claude Code (or any OpenAI-compatible
12
+ client) can talk to.
13
+
14
+ ---
15
+
16
+ ## Install as a CLI
17
+
18
+ This repo uses **pnpm**.
19
+
20
+ ```bash
21
+ git clone https://github.com/maanimeisam/useclaudeproxy.git
22
+ cd useclaudeproxy
23
+ npm install
24
+ npm run build # tsc → dist/index.js (the useclaudeproxy bin)
25
+ npm link # exposes `useclaudeproxy` on your PATH
26
+ ```
27
+
28
+ After linking you can run `useclaudeproxy` from anywhere.
29
+
30
+ ## How it works
31
+
32
+ ```
33
+ useclaudeproxy --model <model>
34
+
35
+ ├─ 1. ensureCliProxy() download CLIProxyAPI (pinned v7.2.142) from GitHub → tools/
36
+ ├─ 2. getValidToken() use stored token ──refresh──▶ run device flow
37
+ │ │ (portal.nousresearch.com)
38
+ │ ▼
39
+ ├─ 3. getAccountInfo() verify the token, print account info
40
+ ├─ 4. setProxyUrl() apply --proxy to tools/config.yaml
41
+ └─ 5. runCliProxy() spawn cli-proxy-api -config tools/config.yaml
42
+ + watch loop transparently refresh the token while it runs
43
+ ```
44
+
45
+ Tokens are persisted at `data/tokens.json` (mode `0o600`). On every refresh the
46
+ provider token is re-injected into `tools/config.yaml` so the proxy keeps
47
+ working without manual re-entry.
48
+
49
+ ## Requirements
50
+
51
+ - **Node.js** ≥ 18
52
+ - **npm** (package manager)
53
+ - One of: Linux (`amd64` / `aarch64`), macOS, Windows, FreeBSD (the binary is
54
+ fetched per-platform from the CLIProxyAPI release)
55
+
56
+ ## Usage
57
+
58
+ The only required flag is `--model` — the upstream model name you want to
59
+ expose through the proxy.
60
+
61
+ ```bash
62
+ # Run the device flow, start the proxy, and keep the token fresh.
63
+ useclaudeproxy --model stealth/ox-alpha
64
+
65
+ # Same thing, routing the proxy's own upstream traffic through a proxy:
66
+ useclaudeproxy --proxy http://127.0.0.1:2080 --model stealth/ox-alpha
67
+ ```
68
+
69
+ On success the CLI prints the env vars to point Claude Code at the local proxy:
70
+
71
+ ```bash
72
+ export ANTHROPIC_MODEL=claude-opus-5
73
+ export ANTHROPIC_BASE_URL=http://127.0.0.1:8317
74
+ export ANTHROPIC_AUTH_TOKEN=456789
75
+ ```
76
+
77
+ ### Global flags
78
+
79
+ These work in **any position** — before or after the command.
80
+
81
+ | Flag | Default | Notes |
82
+ | ------------------- | ------------------ | ------------------------------------------------------------- |
83
+ | `--model <model>` | _(required)_ | Model name to expose in OpenAI compatibility. |
84
+ | `--provider <name>` | `hermes` | OAuth provider to use (hermes only, for now). |
85
+ | `--node-env <env>` | `development` | `development` \| `production`. |
86
+ | `--debug <ns>` | `useclaudeproxy:*` | `debug` namespaces, e.g. `useclaudeproxy:oauth`. |
87
+ | `--data-dir <dir>` | `data` | Token storage directory. |
88
+ | `--proxy <url>` | `""` | CLIProxyAPI outbound proxy (`""`\|`direct`\|`none` to clear). |
89
+ | `--force` | `false` | Re-download the binary even if already installed. |
90
+ | `--renew` | `false` | Re-extract from the kept archive and re-run the device flow. |
91
+
92
+ Example with position-independent flags:
93
+
94
+ ```bash
95
+ useclaudeproxy --data-dir ~/.useclaudeproxy --debug useclaudeproxy:oauth --model stealth/ox-alpha
96
+ # is equivalent to
97
+ useclaudeproxy --model stealth/ox-alpha --data-dir ~/.useclaudeproxy --debug useclaudeproxy:oauth
98
+ ```
99
+
100
+ ## Notes
101
+
102
+ - This repo contains the **TS orchestration app** (`src/`). The actual proxy is
103
+ the third-party `cli-proxy-api` binary fetched from the
104
+ [CLIProxyAPI releases](https://github.com/router-for-me/CLIProxyAPI/releases)
105
+ — it is not part of the TS build.
106
+ - Two independent "proxy" concepts: the TS app's OAuth calls can use an outbound
107
+ proxy (`--proxy`), and the binary has its own separate `proxy-url` for upstream
108
+ provider traffic. They do not affect each other.
109
+ - Providers are pluggable. `hermes` is registered in `src/providers/index.ts`;
110
+ add another by implementing the `Provider` interface in `src/providers/types.ts`.
111
+
112
+ ## License
113
+
114
+ MIT — see [LICENSE](LICENSE).
115
+
116
+ ## Acknowledgements
117
+
118
+ - [**router-for-me/CLIProxyAPI**](https://github.com/router-for-me/CLIProxyAPI)
119
+ — the local OpenAI/Gemini/Claude/Codex-compatible proxy binary this tool
120
+ downloads, configures, and runs. Licensed MIT.
package/dist/app.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function app(): Promise<void>;
2
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAwBA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAiCzC"}
package/dist/app.js ADDED
@@ -0,0 +1,47 @@
1
+ import Debug from "debug";
2
+ import fs from "node:fs";
3
+ import { args } from "./args.js";
4
+ import { setProxyUrl } from "./config-yaml.js";
5
+ import { TOKENS_PATH, WATCH_INTERVAL_MS } from "./config.js";
6
+ import { ensureCliProxy } from "./install-cli-proxy.js";
7
+ import { getProvider } from "./providers/index.js";
8
+ import { runCliProxy } from "./run-cli-proxy.js";
9
+ const log = Debug("useclaudeproxy:oauth");
10
+ const errorLog = Debug("useclaudeproxy:oauth:error");
11
+ function sleep(ms) {
12
+ return new Promise((resolve) => setTimeout(resolve, ms));
13
+ }
14
+ // Clear the stored token so the next getValidToken() re-runs the device flow.
15
+ function clearStoredToken() {
16
+ if (fs.existsSync(TOKENS_PATH)) {
17
+ fs.rmSync(TOKENS_PATH, { force: true });
18
+ log("--renew: cleared stored token");
19
+ }
20
+ }
21
+ export async function app() {
22
+ const provider = getProvider(args.activeProvider);
23
+ log("Starting %s OAuth Device Flow", provider.name);
24
+ await ensureCliProxy();
25
+ // if (args.renew) clearStoredToken();
26
+ const token = await provider.getValidToken();
27
+ const account = await provider.getAccountInfo(token.access_token);
28
+ log("Account Information:\n" + JSON.stringify(account, null, 2));
29
+ setProxyUrl(args.proxy);
30
+ runCliProxy()
31
+ .then((code) => process.exit(code))
32
+ .catch((err) => {
33
+ errorLog("Failed to run CLIProxyAPI: %o", err);
34
+ console.error(err);
35
+ process.exit(1);
36
+ });
37
+ log("Watching token every %dms", WATCH_INTERVAL_MS);
38
+ let current = token.access_token;
39
+ while (true) {
40
+ await sleep(WATCH_INTERVAL_MS);
41
+ const refreshed = await provider.getValidToken();
42
+ const renewed = refreshed.access_token !== current;
43
+ current = refreshed.access_token;
44
+ log(`Token ${renewed ? "RENEWED" : "valid"} (expires_in=${refreshed.expires_in})`);
45
+ }
46
+ }
47
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAiB,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,GAAG,GAAG,KAAK,CAAC,sBAAsB,CAAC,CAAC;AAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,4BAA4B,CAAC,CAAC;AAErD,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,8EAA8E;AAC9E,SAAS,gBAAgB;IACvB,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,QAAQ,GAAa,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5D,GAAG,CAAC,+BAA+B,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEpD,MAAM,cAAc,EAAE,CAAC;IAEvB,sCAAsC;IAEtC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;IAE7C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAClE,GAAG,CAAC,wBAAwB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEjE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,WAAW,EAAE;SACV,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAClC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,QAAQ,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEL,GAAG,CAAC,2BAA2B,EAAE,iBAAiB,CAAC,CAAC;IACpD,IAAI,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;IACjC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,SAAS,CAAC,YAAY,KAAK,OAAO,CAAC;QACnD,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC;QACjC,GAAG,CACD,SAAS,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,gBAAgB,SAAS,CAAC,UAAU,GAAG,CAC9E,CAAC;IACJ,CAAC;AACH,CAAC"}
package/dist/args.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export declare const PROVIDERS: string[];
2
+ interface CliArgs {
3
+ force: boolean;
4
+ nodeEnv: string;
5
+ debug: string;
6
+ dataDir: string;
7
+ proxy: string;
8
+ renew: boolean;
9
+ activeProvider: string;
10
+ provider?: string;
11
+ token?: string;
12
+ proxyUrl?: string;
13
+ model: string;
14
+ }
15
+ export declare const args: CliArgs;
16
+ export {};
17
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,UAAgC,CAAC;AAEvD,UAAU,OAAO;IACf,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAiED,eAAO,MAAM,IAAI,SAAM,CAAC"}
package/dist/args.js ADDED
@@ -0,0 +1,37 @@
1
+ import { Command } from "commander";
2
+ export const PROVIDERS = ["claude", "gemini", "codex"];
3
+ const program = new Command();
4
+ program
5
+ .name("useclaudeproxy")
6
+ .description("Hermes OAuth Device Flow")
7
+ .option("--node-env <env>", "development | production", "development")
8
+ .option("--debug <ns>", 'debug namespaces, e.g. "useclaudeproxy:*"', "useclaudeproxy:*")
9
+ .option("--data-dir <dir>", "token storage directory", "data")
10
+ .requiredOption("--model <model>", "model name to expose in openai-compatibility")
11
+ .option("--proxy <url>", 'CLIProxyAPI outbound proxy (omit for "", or ""|direct|none to clear)')
12
+ .option("--provider <name>", "OAuth provider to use (default: hermes)", "hermes")
13
+ .option("--force", "re-download CLIProxyAPI even if already installed")
14
+ .option("--renew", "re-extract from the kept archive and re-run device flow")
15
+ .parse();
16
+ const cli = {
17
+ force: false,
18
+ nodeEnv: "development",
19
+ debug: "useclaudeproxy:*",
20
+ dataDir: "data",
21
+ proxy: "",
22
+ renew: false,
23
+ activeProvider: "hermes",
24
+ model: "",
25
+ };
26
+ const opts = program.opts();
27
+ process.env.DEBUG = opts.debug;
28
+ cli.nodeEnv = opts.nodeEnv;
29
+ cli.debug = opts.debug;
30
+ cli.dataDir = opts.dataDir;
31
+ cli.proxy = opts.proxy ?? "";
32
+ cli.model = opts.model;
33
+ cli.force = opts.force;
34
+ cli.renew = opts.renew;
35
+ cli.activeProvider = opts.provider;
36
+ export const args = cli;
37
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAgBvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,kBAAkB,EAAE,0BAA0B,EAAE,aAAa,CAAC;KACrE,MAAM,CACL,cAAc,EACd,2CAA2C,EAC3C,kBAAkB,CACnB;KACA,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,CAAC;KAC7D,cAAc,CACb,iBAAiB,EACjB,8CAA8C,CAC/C;KACA,MAAM,CACL,eAAe,EACf,sEAAsE,CACvE;KACA,MAAM,CACL,mBAAmB,EACnB,yCAAyC,EACzC,QAAQ,CACT;KACA,MAAM,CAAC,SAAS,EAAE,mDAAmD,CAAC;KACtE,MAAM,CAAC,SAAS,EAAE,yDAAyD,CAAC;KAC5E,KAAK,EAAE,CAAC;AAEX,MAAM,GAAG,GAAY;IACnB,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,aAAa;IACtB,KAAK,EAAE,kBAAkB;IACzB,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,KAAK;IACZ,cAAc,EAAE,QAAQ;IACxB,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAWxB,CAAC;AAEF,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AAC/B,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;AAC3B,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AACvB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;AAC3B,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;AAC7B,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AACvB,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AACvB,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;AACvB,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC;AAEnC,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const CONFIG_PATH: string;
2
+ export declare function readConfig(filePath?: string): Record<string, any>;
3
+ export declare function writeConfig(config: Record<string, any>, filePath?: string): void;
4
+ export declare function setProxyUrl(proxyUrl: string): void;
5
+ //# sourceMappingURL=config-yaml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-yaml.d.ts","sourceRoot":"","sources":["../src/config-yaml.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,QAKvB,CAAC;AAEF,wBAAgB,UAAU,CACxB,QAAQ,GAAE,MAAoB,GAC7B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAQrB;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,QAAQ,GAAE,MAAoB,GAC7B,IAAI,CAGN;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAalD"}
@@ -0,0 +1,26 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import YAML from "yaml";
4
+ let cache;
5
+ export const CONFIG_PATH = path.join(import.meta.dirname, "..", "tools", "config.yaml");
6
+ export function readConfig(filePath = CONFIG_PATH) {
7
+ if (!cache) {
8
+ cache = (YAML.parse(fs.readFileSync(filePath, "utf8")) ?? {});
9
+ }
10
+ return cache;
11
+ }
12
+ export function writeConfig(config, filePath = CONFIG_PATH) {
13
+ fs.writeFileSync(filePath, YAML.stringify(config), "utf8");
14
+ cache = config;
15
+ }
16
+ export function setProxyUrl(proxyUrl) {
17
+ const url = proxyUrl.trim();
18
+ const PROXY_RE = /^(socks5|http|https):\/\//i;
19
+ if (url !== "" && !/^(direct|none)$/i.test(url) && !PROXY_RE.test(url)) {
20
+ throw new Error(`Invalid proxy-url: ${url} (use http/https/socks5://..., "direct", "none", or "")`);
21
+ }
22
+ const config = readConfig();
23
+ config["proxy-url"] = url;
24
+ writeConfig(config);
25
+ }
26
+ //# sourceMappingURL=config-yaml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-yaml.js","sourceRoot":"","sources":["../src/config-yaml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,IAAI,KAAsC,CAAC;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAClC,OAAO,IAAI,CAAC,OAAO,EACnB,IAAI,EACJ,OAAO,EACP,aAAa,CACd,CAAC;AAEF,MAAM,UAAU,UAAU,CACxB,QAAQ,GAAW,WAAW;IAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAG3D,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,MAA2B,EAC3B,QAAQ,GAAW,WAAW;IAE9B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3D,KAAK,GAAG,MAAM,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,4BAA4B,CAAC;IAE9C,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,yDAAyD,CACnF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC;IAC1B,WAAW,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const config: Readonly<{
2
+ NODE_ENV: "development" | "production";
3
+ DATA_DIR: string;
4
+ DEBUG?: string | undefined;
5
+ }>;
6
+ export type Config = typeof config;
7
+ export declare const TOKENS_PATH: string;
8
+ export declare const WATCH_INTERVAL_MS = 7000;
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,MAAM;;;;EAAgC,CAAC;AACpD,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC;AAKnC,eAAO,MAAM,WAAW,QAA4C,CAAC;AACrE,eAAO,MAAM,iBAAiB,OAAO,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,29 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { z } from "zod";
4
+ import { args } from "./args.js";
5
+ // All config is supplied via CLI flags (see args.ts). Validated with zod and
6
+ // frozen. Importing this module also creates DATA_DIR.
7
+ const envSchema = z.object({
8
+ NODE_ENV: z.enum(["development", "production"]).default("development"),
9
+ DATA_DIR: z.string().default("data"),
10
+ DEBUG: z.string().optional(),
11
+ // Proxy
12
+ });
13
+ const parsedEnv = envSchema.safeParse({
14
+ NODE_ENV: args.nodeEnv,
15
+ DATA_DIR: args.dataDir,
16
+ DEBUG: args.debug,
17
+ });
18
+ if (!parsedEnv.success) {
19
+ console.error("❌ Invalid arguments:");
20
+ console.error(z.prettifyError(parsedEnv.error));
21
+ process.exit(1);
22
+ }
23
+ export const config = Object.freeze(parsedEnv.data);
24
+ fs.mkdirSync(config.DATA_DIR, { recursive: true });
25
+ // Shared token-storage path. Which provider wrote it is the provider's concern;
26
+ // where it lives on disk is core infra.
27
+ export const TOKENS_PATH = path.join(config.DATA_DIR, "tokens.json");
28
+ export const WATCH_INTERVAL_MS = 7000;
29
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,6EAA6E;AAC7E,uDAAuD;AACvD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IACtE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACpC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE5B,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;IACpC,QAAQ,EAAE,IAAI,CAAC,OAAO;IACtB,QAAQ,EAAE,IAAI,CAAC,OAAO;IACtB,KAAK,EAAE,IAAI,CAAC,KAAK;CAClB,CAAC,CAAC;AACH,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACtC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAEpD,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAEnD,gFAAgF;AAChF,wCAAwC;AACxC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type Got } from "got";
2
+ /**
3
+ * Builds a `got` instance configured for the upstream OAuth provider,
4
+ * optionally routed through the configured HTTP(S) proxy.
5
+ *
6
+ * This module has one job: produce a correctly-configured HTTP client.
7
+ * It knows nothing about OAuth flows, device codes, or polling.
8
+ */
9
+ export declare function createOAuthHttpClient(): Got;
10
+ //# sourceMappingURL=http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AACA,OAAY,EAAsB,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAOxD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,GAAG,CAa3C"}
@@ -0,0 +1,33 @@
1
+ import Debug from "debug";
2
+ import got from "got";
3
+ import { HttpProxyAgent } from "http-proxy-agent";
4
+ import { HttpsProxyAgent } from "https-proxy-agent";
5
+ import { args } from "./args.js";
6
+ const log = Debug("app:proxy:upstream-client");
7
+ /**
8
+ * Builds a `got` instance configured for the upstream OAuth provider,
9
+ * optionally routed through the configured HTTP(S) proxy.
10
+ *
11
+ * This module has one job: produce a correctly-configured HTTP client.
12
+ * It knows nothing about OAuth flows, device codes, or polling.
13
+ */
14
+ export function createOAuthHttpClient() {
15
+ log("Proxy=%s", args.proxy);
16
+ const options = {
17
+ https: { rejectUnauthorized: false },
18
+ headers: { "Content-Type": "application/json" },
19
+ retry: { limit: 0 },
20
+ throwHttpErrors: false,
21
+ timeout: { request: undefined },
22
+ ...(args.proxy ? { agent: buildProxyAgents() } : {}),
23
+ };
24
+ return got.extend(options);
25
+ }
26
+ function buildProxyAgents() {
27
+ const agentOptions = { keepAlive: true, keepAliveMsecs: 30_000 };
28
+ return {
29
+ http: new HttpProxyAgent(args.proxy, agentOptions),
30
+ https: new HttpsProxyAgent(args.proxy, agentOptions),
31
+ };
32
+ }
33
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAqC,MAAM,KAAK,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,GAAG,GAAG,KAAK,CAAC,2BAA2B,CAAC,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB;IACnC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAE5B,MAAM,OAAO,GAAkB;QAC7B,KAAK,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE;QACpC,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;QACnB,eAAe,EAAE,KAAK;QACtB,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;QAC/B,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrD,CAAC;IAEF,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,YAAY,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IAEjE,OAAO;QACL,IAAI,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC;QAClD,KAAK,EAAE,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC;KACrD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import Debug from "debug";
3
+ import { app } from "./app.js";
4
+ import { config } from "./config.js";
5
+ import { AccessDeniedError, DeviceCodeExpiredError, OAuthHttpError, } from "./types.js";
6
+ const log = Debug("useclaudeproxy:oauth");
7
+ const errorLog = Debug("useclaudeproxy:oauth:error");
8
+ log("Enviroment: %s", config.NODE_ENV);
9
+ if (config.NODE_ENV === "development" && config.DEBUG)
10
+ Debug.enable(config.DEBUG);
11
+ app().catch((err) => {
12
+ if (err instanceof DeviceCodeExpiredError ||
13
+ err instanceof AccessDeniedError) {
14
+ errorLog(err.message);
15
+ console.error(err.message);
16
+ }
17
+ else if (err instanceof OAuthHttpError) {
18
+ errorLog("OAuth request failed: %s (status=%d) body=%o", err.message, err.statusCode, err.body);
19
+ console.error(err.message);
20
+ }
21
+ else {
22
+ errorLog("Fatal error: %o", err);
23
+ console.error(err);
24
+ }
25
+ process.exit(1);
26
+ });
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,MAAM,GAAG,GAAG,KAAK,CAAC,sBAAsB,CAAC,CAAC;AAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,4BAA4B,CAAC,CAAC;AAErD,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,aAAa,IAAI,MAAM,CAAC,KAAK;IACnD,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAE7B,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAClB,IACE,GAAG,YAAY,sBAAsB;QACrC,GAAG,YAAY,iBAAiB,EAChC,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;QACzC,QAAQ,CACN,8CAA8C,EAC9C,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,IAAI,CACT,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function ensureCliProxy(): Promise<void>;
2
+ //# sourceMappingURL=install-cli-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-cli-proxy.d.ts","sourceRoot":"","sources":["../src/install-cli-proxy.ts"],"names":[],"mappings":"AA8EA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CpD"}
@@ -0,0 +1,140 @@
1
+ import Debug from "debug";
2
+ import got from "got";
3
+ import cp from "node:child_process";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { pipeline } from "node:stream/promises";
8
+ import { args } from "./args.js";
9
+ import { CONFIG_PATH } from "./config-yaml.js";
10
+ import { TOKENS_PATH } from "./config.js";
11
+ const log = Debug("app:install");
12
+ const VERSION = "7.2.142";
13
+ const RELEASE_BASE = `https://github.com/router-for-me/CLIProxyAPI/releases/download/v${VERSION}`;
14
+ const TOOLS_DIR = path.join(import.meta.dirname, "..", "tools");
15
+ function pickAsset() {
16
+ const p = os.platform();
17
+ const a = os.arch();
18
+ let platform;
19
+ let ext;
20
+ switch (p) {
21
+ case "win32":
22
+ platform = "windows";
23
+ ext = "zip";
24
+ break;
25
+ case "darwin":
26
+ platform = "darwin";
27
+ ext = "tar.gz";
28
+ break;
29
+ case "freebsd":
30
+ platform = "freebsd";
31
+ ext = "tar.gz";
32
+ break;
33
+ case "linux":
34
+ platform = "linux";
35
+ ext = "tar.gz";
36
+ break;
37
+ default:
38
+ throw new Error(`Unsupported platform: ${p}`);
39
+ }
40
+ let arch;
41
+ switch (a) {
42
+ case "x64":
43
+ arch = "amd64";
44
+ break;
45
+ case "arm64":
46
+ arch = "aarch64";
47
+ break;
48
+ default:
49
+ throw new Error(`Unsupported architecture: ${a}`);
50
+ }
51
+ return `CLIProxyAPI_${VERSION}_${platform}_${arch}.${ext}`;
52
+ }
53
+ async function download(url, dest) {
54
+ const stream = got.stream(url);
55
+ stream.on("downloadProgress", ({ transferred, total, percent }) => {
56
+ const t = (transferred / 1e6).toFixed(1);
57
+ const totalStr = total ? `/${(total / 1e6).toFixed(1)}` : "";
58
+ const pct = total ? ` (${(percent * 100).toFixed(0)}%)` : "";
59
+ process.stderr.write(`\r⬇️ ${t}MB${totalStr}${pct}`);
60
+ });
61
+ try {
62
+ await pipeline(stream, fs.createWriteStream(dest));
63
+ }
64
+ finally {
65
+ process.stderr.write("\n");
66
+ }
67
+ }
68
+ function extract(archivePath, destDir) {
69
+ const flag = archivePath.endsWith(".zip") ? "-xf" : "-xzf";
70
+ cp.execFileSync("tar", [flag, archivePath, "-C", destDir], {
71
+ stdio: "inherit",
72
+ });
73
+ }
74
+ export async function ensureCliProxy() {
75
+ const asset = pickAsset();
76
+ const url = `${RELEASE_BASE}/${asset}`;
77
+ const archivePath = path.join(TOOLS_DIR, asset);
78
+ // --renew: re-extract from the kept archive, then app.ts re-runs the device flow.
79
+ if (args.renew) {
80
+ if (fs.existsSync(TOKENS_PATH)) {
81
+ fs.rmSync(TOKENS_PATH, { force: true });
82
+ log("--renew: cleared stored token, will re-run device flow");
83
+ }
84
+ renewFromArchive(archivePath);
85
+ return;
86
+ }
87
+ if (fs.existsSync(TOOLS_DIR) &&
88
+ fs.readdirSync(TOOLS_DIR).length > 0 &&
89
+ !args.force) {
90
+ log("CLIProxyAPI already present at %s, skipping download", TOOLS_DIR);
91
+ return;
92
+ }
93
+ if (args.force) {
94
+ console.warn(`⚠️ --force set: re-downloading archive and overwriting extracted files in ${TOOLS_DIR}`);
95
+ }
96
+ fs.mkdirSync(TOOLS_DIR, { recursive: true });
97
+ // Keep the archive alongside the extracted files (no .tmp- + rm).
98
+ if (!fs.existsSync(archivePath)) {
99
+ console.error(`⬇️ Downloading from ${url}`);
100
+ log("Downloading %s", url);
101
+ await download(url, archivePath);
102
+ }
103
+ else {
104
+ log("Archive already present, skipping download: %s", archivePath);
105
+ }
106
+ extract(archivePath, TOOLS_DIR);
107
+ log("Installed CLIProxyAPI to %s", TOOLS_DIR);
108
+ createConfig();
109
+ }
110
+ function renewFromArchive(archivePath) {
111
+ if (!fs.existsSync(archivePath)) {
112
+ console.error("❌ No archive at " +
113
+ archivePath +
114
+ " to renew from — run once without --renew to fetch it.");
115
+ process.exit(1);
116
+ }
117
+ const keep = new Set([path.basename(archivePath)]);
118
+ for (const name of fs.readdirSync(TOOLS_DIR)) {
119
+ if (keep.has(name))
120
+ continue;
121
+ fs.rmSync(path.join(TOOLS_DIR, name), { recursive: true, force: true });
122
+ }
123
+ extract(archivePath, TOOLS_DIR);
124
+ log("Renewed CLIProxyAPI from %s", archivePath);
125
+ createConfig();
126
+ args.renew = false;
127
+ }
128
+ // ponytail: only seeds when live config absent — never clobbers an edited one
129
+ function createConfig() {
130
+ const example = path.join(TOOLS_DIR, "config.example.yaml");
131
+ if (!fs.existsSync(example)) {
132
+ console.error(`❌ Missing template: ${example}`);
133
+ process.exit(1);
134
+ }
135
+ if (fs.existsSync(CONFIG_PATH))
136
+ return;
137
+ fs.copyFileSync(example, CONFIG_PATH);
138
+ log("Seeded %s from %s", CONFIG_PATH, example);
139
+ }
140
+ //# sourceMappingURL=install-cli-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-cli-proxy.js","sourceRoot":"","sources":["../src/install-cli-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type TokenResponse } from "../types.ts";
2
+ import type { Provider } from "./types.ts";
3
+ export declare class HermesProvider implements Provider {
4
+ readonly name = "hermes";
5
+ private readonly client;
6
+ getValidToken(): Promise<TokenResponse>;
7
+ getAccountInfo(accessToken: string): Promise<Record<string, unknown>>;
8
+ private runDeviceFlow;
9
+ private readStoredToken;
10
+ private saveTokens;
11
+ private initConfig;
12
+ private setApiKey;
13
+ }
14
+ export declare const hermesProvider: HermesProvider;
15
+ //# sourceMappingURL=hermes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../src/providers/hermes.ts"],"names":[],"mappings":"AAOA,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA8H3C,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IAEjD,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAwB5C;IAEK,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAE1E;YAEa,aAAa;IAoB3B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,UAAU;IAiDlB,OAAO,CAAC,SAAS;CASlB;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC"}