theclawbay 0.1.15 → 0.2.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 (51) hide show
  1. package/README.md +35 -45
  2. package/dist/commands/link.d.ts +1 -4
  3. package/dist/commands/link.js +13 -47
  4. package/dist/commands/proxy.d.ts +12 -0
  5. package/dist/commands/proxy.js +179 -0
  6. package/dist/lib/base-command.d.ts +0 -1
  7. package/dist/lib/base-command.js +2 -6
  8. package/dist/lib/config/paths.d.ts +0 -13
  9. package/dist/lib/config/paths.js +1 -84
  10. package/dist/lib/errors.d.ts +3 -0
  11. package/dist/lib/errors.js +10 -0
  12. package/dist/lib/managed/config.d.ts +1 -5
  13. package/dist/lib/managed/config.js +8 -47
  14. package/dist/lib/managed/errors.d.ts +4 -4
  15. package/dist/lib/managed/errors.js +4 -4
  16. package/dist/lib/update-check.js +10 -13
  17. package/package.json +6 -10
  18. package/dist/commands/agent.d.ts +0 -12
  19. package/dist/commands/agent.js +0 -545
  20. package/dist/commands/current.d.ts +0 -8
  21. package/dist/commands/current.js +0 -29
  22. package/dist/commands/list.d.ts +0 -8
  23. package/dist/commands/list.js +0 -36
  24. package/dist/commands/save.d.ts +0 -11
  25. package/dist/commands/save.js +0 -30
  26. package/dist/commands/usage.d.ts +0 -5
  27. package/dist/commands/usage.js +0 -68
  28. package/dist/commands/use.d.ts +0 -12
  29. package/dist/commands/use.js +0 -91
  30. package/dist/lib/accounts/account-service.d.ts +0 -21
  31. package/dist/lib/accounts/account-service.js +0 -201
  32. package/dist/lib/accounts/errors.d.ts +0 -24
  33. package/dist/lib/accounts/errors.js +0 -61
  34. package/dist/lib/accounts/index.d.ts +0 -7
  35. package/dist/lib/accounts/index.js +0 -24
  36. package/dist/lib/accounts/runtime.d.ts +0 -9
  37. package/dist/lib/accounts/runtime.js +0 -62
  38. package/dist/lib/agent/account-login.d.ts +0 -22
  39. package/dist/lib/agent/account-login.js +0 -1408
  40. package/dist/lib/agent/rollout-log.d.ts +0 -1
  41. package/dist/lib/agent/rollout-log.js +0 -72
  42. package/dist/lib/agent/round-robin.d.ts +0 -2
  43. package/dist/lib/agent/round-robin.js +0 -28
  44. package/dist/lib/agent/sync-accounts.d.ts +0 -15
  45. package/dist/lib/agent/sync-accounts.js +0 -199
  46. package/dist/lib/agent/token-count-watcher.d.ts +0 -33
  47. package/dist/lib/agent/token-count-watcher.js +0 -224
  48. package/dist/lib/agent/usage-store.d.ts +0 -23
  49. package/dist/lib/agent/usage-store.js +0 -125
  50. package/dist/lib/managed/backend-client.d.ts +0 -54
  51. package/dist/lib/managed/backend-client.js +0 -90
package/README.md CHANGED
@@ -1,77 +1,67 @@
1
1
  # The Claw Bay (`theclawbay`)
2
2
 
3
- `theclawbay` is a CLI for customers of `theclawbay.com`.
4
- Its main job is to auto-switch between Codex accounts assigned from your web app, so users can keep working without manual login/logout churn.
3
+ `theclawbay` is a customer CLI for The Claw Bay.
5
4
 
6
- > [!WARNING]
7
- > Not affiliated with OpenAI or Codex. Not an official tool.
8
-
9
- ## Main Functionality
5
+ It now does one job:
10
6
 
11
- For end users, the normal flow is:
7
+ - link your purchased API key
8
+ - run a local relay that forwards Codex/OpenAI requests to your The Claw Bay backend
12
9
 
13
- 1. Install `theclawbay`
14
- 2. Link with API key from `theclawbay.com`
15
- 3. Run `theclawbay agent`
16
- 4. Agent auto-manages account sessions and switches accounts locally when limits are reached
10
+ This package no longer runs local account login automation or local account switching flows.
17
11
 
18
- Internally, switching happens by updating the active `~/.codex/auth.json` from managed snapshots in `~/.codex/accounts/*.json`.
12
+ > Not affiliated with OpenAI or Codex. Not an official tool.
19
13
 
20
14
  ## Requirements
21
15
 
22
16
  - Node.js 18+
23
- - Codex CLI in `PATH` (`codex` command)
24
- - Python 3
25
- - Chrome/Chromium browser (or set `THECLAWBAY_ZENDRIVER_BROWSER_BIN`)
17
+ - Codex CLI installed (`@openai/codex`)
26
18
 
27
19
  ## Install
28
20
 
29
- ### Linux/macOS (recommended)
30
-
31
21
  ```sh
32
- curl -fsSL https://theclawbay.com/install.sh | bash
33
- ```
34
-
35
- Run this as a regular user (not `root`/`sudo`).
36
- The installer uses deterministic user-owned paths:
37
-
38
- - npm global prefix: `~/.local/share/theclawbay/npm`
39
- - Python env: `~/.local/share/theclawbay/py-venv`
40
- - CLI launch path: `~/.local/bin`
41
-
42
- ### Windows (PowerShell)
43
-
44
- ```powershell
45
- # Run as Administrator
46
- winget install -e --id OpenJS.NodeJS.LTS
47
- winget install -e --id Python.Python.3.12
48
- winget install -e --id Google.Chrome
49
- npm i -g @openai/codex
50
- python -m pip install --user --upgrade pip zendriver
51
22
  npm i -g theclawbay
52
23
  ```
53
24
 
54
- ## Link and Run
25
+ ## Link
55
26
 
56
- 1. Go to `https://theclawbay.com`, purchase a plan, and copy your API key from the dashboard.
57
- 2. Link your machine:
27
+ Use your purchased API key from your dashboard:
58
28
 
59
29
  ```sh
60
30
  theclawbay link --api-key <apiKey>
61
31
  ```
62
32
 
63
- 3. Start the agent:
33
+ This defaults to `https://theclawbay.com`.
34
+
35
+ If you operate a custom backend, pass it explicitly:
64
36
 
65
37
  ```sh
66
- theclawbay agent
38
+ theclawbay link --api-key <apiKey> --backend https://your-domain.com
67
39
  ```
68
40
 
69
- Optional troubleshooting (shows browser automation live):
41
+ ## Run Relay
70
42
 
71
43
  ```sh
72
- theclawbay agent --showBrowser
44
+ theclawbay proxy
73
45
  ```
74
46
 
75
- ## Need More Details?
47
+ By default this starts a local relay on `http://127.0.0.1:2455` and forwards to:
48
+
49
+ - `https://theclawbay.com/api/codex-auth/v1/proxy/...`
50
+
51
+ The command prints a ready-to-paste Codex provider snippet.
52
+
53
+ ## Common Flags
54
+
55
+ `theclawbay proxy` supports:
56
+
57
+ - `--host` local bind host (default `127.0.0.1`)
58
+ - `--port` local bind port (default `2455`)
59
+ - `--backend` override backend URL from linked config
60
+ - `--api-key` override API key from linked config
61
+ - `--base-path` override server proxy path (default `/api/codex-auth/v1/proxy`)
62
+
63
+ ## Notes
76
64
 
77
- - End-user onboarding and billing are handled in `https://theclawbay.com`.
65
+ - End users only need API keys. They do not need upstream account credentials.
66
+ - Keep your backend on HTTPS for WAN usage.
67
+ - Linked config is stored at `~/.codex/theclawbay.managed.json`.
@@ -3,10 +3,7 @@ export default class LinkCommand extends BaseCommand {
3
3
  static description: string;
4
4
  static flags: {
5
5
  backend: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
- "api-key": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- "seat-id": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- "device-token": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- "poll-interval-ms": import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
+ "api-key": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
7
  };
11
8
  run(): Promise<void>;
12
9
  }
@@ -5,69 +5,35 @@ const base_command_1 = require("../lib/base-command");
5
5
  const config_1 = require("../lib/managed/config");
6
6
  const paths_1 = require("../lib/config/paths");
7
7
  const api_key_1 = require("../lib/managed/api-key");
8
+ const DEFAULT_BACKEND_URL = "https://theclawbay.com";
8
9
  class LinkCommand extends base_command_1.BaseCommand {
9
10
  async run() {
10
11
  await this.runSafe(async () => {
11
12
  const { flags } = await this.parse(LinkCommand);
12
13
  const apiKey = flags["api-key"];
13
- const seatId = flags["seat-id"];
14
- const deviceToken = flags["device-token"];
15
- const pollIntervalMs = flags["poll-interval-ms"];
16
14
  const backendUrlFlag = flags.backend;
17
- if (apiKey) {
18
- const backendUrl = backendUrlFlag !== null && backendUrlFlag !== void 0 ? backendUrlFlag : (0, api_key_1.tryInferBackendUrlFromApiKey)(apiKey);
19
- if (!backendUrl) {
20
- throw new Error('Backend URL is required. Pass "--backend https://YOUR_ADMIN_APP", or use an API key created by the web app (new keys encode the backend URL).');
21
- }
22
- await (0, config_1.writeManagedConfig)({
23
- backendUrl,
24
- authType: "apiKey",
25
- apiKey,
26
- pollIntervalMs,
27
- });
28
- }
29
- else {
30
- if (!backendUrlFlag) {
31
- throw new Error('Backend URL is required for seat mode. Pass "--backend https://YOUR_ADMIN_APP".');
32
- }
33
- await (0, config_1.writeManagedConfig)({
34
- backendUrl: backendUrlFlag,
35
- authType: "seat",
36
- seatId,
37
- deviceToken,
38
- pollIntervalMs,
39
- });
40
- }
15
+ const inferredBackendUrl = (0, api_key_1.tryInferBackendUrlFromApiKey)(apiKey);
16
+ const backendUrl = backendUrlFlag ?? inferredBackendUrl ?? DEFAULT_BACKEND_URL;
17
+ await (0, config_1.writeManagedConfig)({
18
+ backendUrl,
19
+ apiKey,
20
+ });
41
21
  this.log(`Linked. Managed config written to ${paths_1.managedConfigPath}`);
42
- this.log(`Run "theclawbay agent" to start managed switching.`);
22
+ this.log(`Backend: ${backendUrl}`);
23
+ this.log(`Run "theclawbay proxy" to start the local relay.`);
43
24
  });
44
25
  }
45
26
  }
46
- LinkCommand.description = "Link this Codex Auth install to your management web app";
27
+ LinkCommand.description = "Link this machine to your The Claw Bay API backend using an API key";
47
28
  LinkCommand.flags = {
48
29
  backend: core_1.Flags.string({
49
30
  required: false,
50
- description: "Backend base URL (e.g. https://admin.example.com)",
31
+ description: "Backend base URL override (default: https://theclawbay.com)",
51
32
  }),
52
33
  "api-key": core_1.Flags.string({
53
- required: false,
34
+ required: true,
54
35
  aliases: ["apiKey"],
55
- description: "API key issued by your admin web app (recommended)",
56
- }),
57
- "seat-id": core_1.Flags.string({
58
- required: false,
59
- aliases: ["seatId"],
60
- description: "[legacy] Seat ID issued by your admin web app",
61
- }),
62
- "device-token": core_1.Flags.string({
63
- required: false,
64
- aliases: ["deviceToken"],
65
- description: "[legacy] Device token issued by your admin web app",
66
- }),
67
- "poll-interval-ms": core_1.Flags.integer({
68
- required: false,
69
- aliases: ["pollIntervalMs"],
70
- description: "Override backend poll interval (ms)",
36
+ description: "API key issued by your The Claw Bay dashboard",
71
37
  }),
72
38
  };
73
39
  exports.default = LinkCommand;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../lib/base-command";
2
+ export default class ProxyCommand extends BaseCommand {
3
+ static description: string;
4
+ static flags: {
5
+ host: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
6
+ port: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ backend: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ "api-key": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ "base-path": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_http_1 = __importDefault(require("node:http"));
7
+ const node_stream_1 = require("node:stream");
8
+ const core_1 = require("@oclif/core");
9
+ const base_command_1 = require("../lib/base-command");
10
+ const config_1 = require("../lib/managed/config");
11
+ function trimTrailingSlash(value) {
12
+ return value.replace(/\/+$/g, "");
13
+ }
14
+ function ensureLeadingSlash(value) {
15
+ return value.startsWith("/") ? value : `/${value}`;
16
+ }
17
+ function joinUrl(base, pathname) {
18
+ const url = new URL(base);
19
+ url.pathname = `${url.pathname.replace(/\/+$/g, "")}${pathname.startsWith("/") ? "" : "/"}${pathname}`;
20
+ return url.toString();
21
+ }
22
+ function normalizeUrl(raw, label) {
23
+ try {
24
+ const parsed = new URL(raw.trim());
25
+ return trimTrailingSlash(parsed.toString());
26
+ }
27
+ catch {
28
+ throw new Error(`invalid ${label} URL: ${raw}`);
29
+ }
30
+ }
31
+ function headersFromIncoming(source) {
32
+ const headers = new Headers();
33
+ for (const [key, value] of Object.entries(source)) {
34
+ if (!value)
35
+ continue;
36
+ const lower = key.toLowerCase();
37
+ if (lower === "host" || lower === "content-length" || lower === "authorization" || lower === "connection") {
38
+ continue;
39
+ }
40
+ if (Array.isArray(value)) {
41
+ headers.set(key, value.join(", "));
42
+ }
43
+ else {
44
+ headers.set(key, value);
45
+ }
46
+ }
47
+ return headers;
48
+ }
49
+ async function readIncomingBody(req) {
50
+ if (!req.method || req.method === "GET" || req.method === "HEAD")
51
+ return null;
52
+ const chunks = [];
53
+ for await (const chunk of req) {
54
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
55
+ }
56
+ if (!chunks.length)
57
+ return null;
58
+ return Buffer.concat(chunks);
59
+ }
60
+ function bufferToArrayBuffer(buffer) {
61
+ const bytes = new Uint8Array(buffer.length);
62
+ bytes.set(buffer);
63
+ return bytes.buffer;
64
+ }
65
+ function writeUpstreamHeaders(res, source) {
66
+ source.forEach((value, key) => {
67
+ const lower = key.toLowerCase();
68
+ if (lower === "connection" || lower === "transfer-encoding" || lower === "keep-alive")
69
+ return;
70
+ res.setHeader(key, value);
71
+ });
72
+ }
73
+ class ProxyCommand extends base_command_1.BaseCommand {
74
+ async run() {
75
+ await this.runSafe(async () => {
76
+ const { flags } = await this.parse(ProxyCommand);
77
+ const managed = await (0, config_1.readManagedConfig)();
78
+ if (!managed.apiKey?.trim()) {
79
+ throw new Error('API key auth is required. Re-link using "theclawbay link --api-key <key>".');
80
+ }
81
+ const backendUrl = normalizeUrl(flags.backend ?? managed.backendUrl, "--backend");
82
+ const apiKey = (flags["api-key"] ?? managed.apiKey ?? "").trim();
83
+ if (!apiKey) {
84
+ throw new Error("API key is required for WAN proxy mode.");
85
+ }
86
+ const basePath = ensureLeadingSlash(flags["base-path"].trim()).replace(/\/+$/g, "");
87
+ const proxyBase = `${trimTrailingSlash(backendUrl)}${basePath}`;
88
+ const server = node_http_1.default.createServer(async (req, res) => {
89
+ const method = req.method?.toUpperCase() ?? "GET";
90
+ const incomingUrl = new URL(req.url || "/", "http://local-proxy.invalid");
91
+ const routePath = incomingUrl.pathname.replace(/^\/+/, "");
92
+ const upstreamUrl = joinUrl(proxyBase, routePath);
93
+ const urlWithQuery = `${upstreamUrl}${incomingUrl.search || ""}`;
94
+ try {
95
+ const headers = headersFromIncoming(req.headers);
96
+ headers.set("Authorization", `Bearer ${apiKey}`);
97
+ const bodyBuffer = await readIncomingBody(req);
98
+ const body = bodyBuffer ? bufferToArrayBuffer(bodyBuffer) : undefined;
99
+ const upstream = await fetch(urlWithQuery, {
100
+ method,
101
+ headers,
102
+ body,
103
+ redirect: "manual",
104
+ });
105
+ res.statusCode = upstream.status;
106
+ res.statusMessage = upstream.statusText;
107
+ writeUpstreamHeaders(res, upstream.headers);
108
+ if (!upstream.body || method === "HEAD") {
109
+ res.end();
110
+ return;
111
+ }
112
+ const stream = node_stream_1.Readable.fromWeb(upstream.body);
113
+ stream.on("error", () => {
114
+ res.destroy();
115
+ });
116
+ stream.pipe(res);
117
+ }
118
+ catch (error) {
119
+ const message = error instanceof Error ? error.message : String(error);
120
+ res.statusCode = 502;
121
+ res.setHeader("Content-Type", "application/json");
122
+ res.end(JSON.stringify({ error: `proxy relay failed: ${message}` }));
123
+ }
124
+ });
125
+ await new Promise((resolve, reject) => {
126
+ server.once("error", reject);
127
+ server.listen(flags.port, flags.host, () => {
128
+ server.off("error", reject);
129
+ resolve();
130
+ });
131
+ });
132
+ const localBase = `http://${flags.host}:${flags.port}`;
133
+ this.log(`theclawbay WAN relay listening at ${localBase}`);
134
+ this.log(`Forwarding to ${proxyBase}`);
135
+ this.log("");
136
+ this.log("Codex CLI config snippet:");
137
+ this.log('model_provider = "theclawbay-wan"');
138
+ this.log("");
139
+ this.log("[model_providers.theclawbay-wan]");
140
+ this.log('name = "OpenAI"');
141
+ this.log(`base_url = "${localBase}/backend-api/codex"`);
142
+ this.log('wire_api = "responses"');
143
+ this.log(`chatgpt_base_url = "${localBase}"`);
144
+ this.log("requires_openai_auth = true");
145
+ await new Promise((resolve) => {
146
+ const stop = () => {
147
+ server.close(() => resolve());
148
+ };
149
+ process.once("SIGINT", stop);
150
+ process.once("SIGTERM", stop);
151
+ });
152
+ });
153
+ }
154
+ }
155
+ ProxyCommand.description = "Run a local relay that forwards Codex/OpenAI requests to your The Claw Bay backend using API-key auth";
156
+ ProxyCommand.flags = {
157
+ host: core_1.Flags.string({
158
+ default: "127.0.0.1",
159
+ description: "Local bind host",
160
+ }),
161
+ port: core_1.Flags.integer({
162
+ default: 2455,
163
+ description: "Local bind port",
164
+ }),
165
+ backend: core_1.Flags.string({
166
+ required: false,
167
+ description: "Override backend URL (defaults to linked managed backend)",
168
+ }),
169
+ "api-key": core_1.Flags.string({
170
+ required: false,
171
+ aliases: ["apiKey"],
172
+ description: "Override API key (defaults to linked managed API key)",
173
+ }),
174
+ "base-path": core_1.Flags.string({
175
+ default: "/api/codex-auth/v1/proxy",
176
+ description: "Server proxy base path",
177
+ }),
178
+ };
179
+ exports.default = ProxyCommand;
@@ -1,6 +1,5 @@
1
1
  import { Command } from "@oclif/core";
2
2
  export declare abstract class BaseCommand extends Command {
3
- protected readonly accounts: import("./accounts").AccountService;
4
3
  protected runSafe(action: () => Promise<void>): Promise<void>;
5
4
  private handleError;
6
5
  }
@@ -2,13 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseCommand = void 0;
4
4
  const core_1 = require("@oclif/core");
5
- const accounts_1 = require("./accounts");
5
+ const errors_1 = require("./errors");
6
6
  const update_check_1 = require("./update-check");
7
7
  class BaseCommand extends core_1.Command {
8
- constructor() {
9
- super(...arguments);
10
- this.accounts = accounts_1.accountService;
11
- }
12
8
  async runSafe(action) {
13
9
  try {
14
10
  await (0, update_check_1.maybeNotifyUpdate)({
@@ -23,7 +19,7 @@ class BaseCommand extends core_1.Command {
23
19
  }
24
20
  }
25
21
  handleError(error) {
26
- if (error instanceof accounts_1.CodexAuthError) {
22
+ if (error instanceof errors_1.ClawBayError) {
27
23
  this.error(error.message);
28
24
  }
29
25
  if (error instanceof Error) {
@@ -1,18 +1,5 @@
1
1
  export declare const codexDir: string;
2
- export declare const accountsDir: string;
3
- export declare const authPath: string;
4
- export declare const currentNamePath: string;
5
- export declare const sessionsDir: string;
6
2
  export declare const managedConfigPath: string;
7
- export declare const managedAccountsStatePath: string;
8
- export declare const usageStatePath: string;
9
- export declare const usageHistoryPath: string;
10
3
  export declare const updateCheckStatePath: string;
11
4
  export declare const legacyManagedConfigPathClayBay: string;
12
5
  export declare const legacyManagedConfigPathCodexAuth: string;
13
- export declare function resolveOpenClawStateDir(): string;
14
- export declare function resolveOpenClawAgentDir(): string;
15
- export declare function resolveOpenClawAuthStorePath(): string;
16
- export declare function resolveOpenClawLegacyAuthPath(): string;
17
- export declare function resolveOpenClawAccountsDir(): string;
18
- export declare function resolveOpenClawCurrentNamePath(): string;
@@ -3,94 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.legacyManagedConfigPathCodexAuth = exports.legacyManagedConfigPathClayBay = exports.updateCheckStatePath = exports.usageHistoryPath = exports.usageStatePath = exports.managedAccountsStatePath = exports.managedConfigPath = exports.sessionsDir = exports.currentNamePath = exports.authPath = exports.accountsDir = exports.codexDir = void 0;
7
- exports.resolveOpenClawStateDir = resolveOpenClawStateDir;
8
- exports.resolveOpenClawAgentDir = resolveOpenClawAgentDir;
9
- exports.resolveOpenClawAuthStorePath = resolveOpenClawAuthStorePath;
10
- exports.resolveOpenClawLegacyAuthPath = resolveOpenClawLegacyAuthPath;
11
- exports.resolveOpenClawAccountsDir = resolveOpenClawAccountsDir;
12
- exports.resolveOpenClawCurrentNamePath = resolveOpenClawCurrentNamePath;
13
- const node_fs_1 = __importDefault(require("node:fs"));
6
+ exports.legacyManagedConfigPathCodexAuth = exports.legacyManagedConfigPathClayBay = exports.updateCheckStatePath = exports.managedConfigPath = exports.codexDir = void 0;
14
7
  const node_os_1 = __importDefault(require("node:os"));
15
8
  const node_path_1 = __importDefault(require("node:path"));
16
9
  exports.codexDir = node_path_1.default.join(node_os_1.default.homedir(), ".codex");
17
- exports.accountsDir = node_path_1.default.join(exports.codexDir, "accounts");
18
- exports.authPath = node_path_1.default.join(exports.codexDir, "auth.json");
19
- exports.currentNamePath = node_path_1.default.join(exports.codexDir, "current");
20
- exports.sessionsDir = node_path_1.default.join(exports.codexDir, "sessions");
21
10
  exports.managedConfigPath = node_path_1.default.join(exports.codexDir, "theclawbay.managed.json");
22
- exports.managedAccountsStatePath = node_path_1.default.join(exports.codexDir, "theclawbay.accounts-state.json");
23
- exports.usageStatePath = node_path_1.default.join(exports.codexDir, "theclawbay.usage-state.json");
24
- exports.usageHistoryPath = node_path_1.default.join(exports.codexDir, "theclawbay.usage-history.jsonl");
25
11
  exports.updateCheckStatePath = node_path_1.default.join(exports.codexDir, "theclawbay.update-check.json");
26
12
  exports.legacyManagedConfigPathClayBay = node_path_1.default.join(exports.codexDir, "theclaybay.managed.json");
27
13
  exports.legacyManagedConfigPathCodexAuth = node_path_1.default.join(exports.codexDir, "codex-auth.managed.json");
28
- const OPENCLAW_LEGACY_STATE_DIRNAMES = [".clawdbot", ".moltbot", ".moldbot"];
29
- function normalizeEnvPath(rawValue) {
30
- if (typeof rawValue !== "string")
31
- return null;
32
- const trimmed = rawValue.trim();
33
- return trimmed.length ? trimmed : null;
34
- }
35
- function resolveEffectiveHomeDir() {
36
- var _a, _b;
37
- const explicitHome = normalizeEnvPath(process.env.OPENCLAW_HOME);
38
- const systemHome = (_b = (_a = normalizeEnvPath(process.env.HOME)) !== null && _a !== void 0 ? _a : normalizeEnvPath(process.env.USERPROFILE)) !== null && _b !== void 0 ? _b : node_os_1.default.homedir();
39
- if (!explicitHome) {
40
- return node_path_1.default.resolve(systemHome);
41
- }
42
- if (explicitHome === "~" || explicitHome.startsWith("~/") || explicitHome.startsWith("~\\")) {
43
- return node_path_1.default.resolve(explicitHome.replace(/^~(?=$|[\\/])/, systemHome));
44
- }
45
- return node_path_1.default.resolve(explicitHome);
46
- }
47
- function resolveUserPath(rawPath) {
48
- const trimmed = rawPath.trim();
49
- if (trimmed.startsWith("~")) {
50
- return node_path_1.default.resolve(trimmed.replace(/^~(?=$|[\\/])/, resolveEffectiveHomeDir()));
51
- }
52
- return node_path_1.default.resolve(trimmed);
53
- }
54
- function pathExistsSync(targetPath) {
55
- try {
56
- return node_fs_1.default.existsSync(targetPath);
57
- }
58
- catch {
59
- return false;
60
- }
61
- }
62
- function resolveOpenClawStateDir() {
63
- var _a;
64
- const override = (_a = normalizeEnvPath(process.env.OPENCLAW_STATE_DIR)) !== null && _a !== void 0 ? _a : normalizeEnvPath(process.env.CLAWDBOT_STATE_DIR);
65
- if (override)
66
- return resolveUserPath(override);
67
- const home = resolveEffectiveHomeDir();
68
- const openClawDir = node_path_1.default.join(home, ".openclaw");
69
- if (pathExistsSync(openClawDir))
70
- return openClawDir;
71
- for (const legacyDirName of OPENCLAW_LEGACY_STATE_DIRNAMES) {
72
- const legacyDir = node_path_1.default.join(home, legacyDirName);
73
- if (pathExistsSync(legacyDir))
74
- return legacyDir;
75
- }
76
- return openClawDir;
77
- }
78
- function resolveOpenClawAgentDir() {
79
- var _a;
80
- const override = (_a = normalizeEnvPath(process.env.OPENCLAW_AGENT_DIR)) !== null && _a !== void 0 ? _a : normalizeEnvPath(process.env.PI_CODING_AGENT_DIR);
81
- if (override)
82
- return resolveUserPath(override);
83
- return node_path_1.default.join(resolveOpenClawStateDir(), "agents", "default", "agent");
84
- }
85
- function resolveOpenClawAuthStorePath() {
86
- return node_path_1.default.join(resolveOpenClawAgentDir(), "auth-profiles.json");
87
- }
88
- function resolveOpenClawLegacyAuthPath() {
89
- return node_path_1.default.join(resolveOpenClawAgentDir(), "auth.json");
90
- }
91
- function resolveOpenClawAccountsDir() {
92
- return node_path_1.default.join(resolveOpenClawStateDir(), "accounts");
93
- }
94
- function resolveOpenClawCurrentNamePath() {
95
- return node_path_1.default.join(resolveOpenClawStateDir(), "current");
96
- }
@@ -0,0 +1,3 @@
1
+ export declare class ClawBayError extends Error {
2
+ constructor(message: string);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClawBayError = void 0;
4
+ class ClawBayError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "ClawBayError";
8
+ }
9
+ }
10
+ exports.ClawBayError = ClawBayError;
@@ -1,10 +1,6 @@
1
1
  export type ManagedConfig = {
2
2
  backendUrl: string;
3
- authType: "seat" | "apiKey";
4
- seatId?: string;
5
- deviceToken?: string;
6
- apiKey?: string;
7
- pollIntervalMs?: number;
3
+ apiKey: string;
8
4
  };
9
5
  export declare function readManagedConfig(): Promise<ManagedConfig>;
10
6
  export declare function writeManagedConfig(config: ManagedConfig): Promise<void>;
@@ -72,70 +72,31 @@ async function readManagedConfig() {
72
72
  throw new errors_1.ManagedConfigInvalidError("backendUrl is required");
73
73
  }
74
74
  const backendUrl = normalizeAndValidateBackendUrl(obj.backendUrl);
75
- const authType = obj.authType;
76
- if (authType !== "seat" && authType !== "apiKey") {
77
- throw new errors_1.ManagedConfigInvalidError('authType must be "seat" or "apiKey"');
75
+ if (obj.authType === "seat") {
76
+ throw new errors_1.ManagedConfigInvalidError('legacy seat-mode config is no longer supported; run "theclawbay link --api-key <key>" to relink');
78
77
  }
79
- if (authType === "seat") {
80
- if (typeof obj.seatId !== "string" || !obj.seatId.trim()) {
81
- throw new errors_1.ManagedConfigInvalidError("seatId is required for authType=seat");
82
- }
83
- if (typeof obj.deviceToken !== "string" || !obj.deviceToken.trim()) {
84
- throw new errors_1.ManagedConfigInvalidError("deviceToken is required for authType=seat");
85
- }
86
- }
87
- else {
88
- if (typeof obj.apiKey !== "string" || !obj.apiKey.trim()) {
89
- throw new errors_1.ManagedConfigInvalidError("apiKey is required for authType=apiKey");
90
- }
91
- }
92
- const pollIntervalMs = obj.pollIntervalMs === undefined ? undefined : Number(obj.pollIntervalMs);
93
- if (pollIntervalMs !== undefined && (!Number.isFinite(pollIntervalMs) || pollIntervalMs < 250)) {
94
- throw new errors_1.ManagedConfigInvalidError("pollIntervalMs must be >= 250");
78
+ if (typeof obj.apiKey !== "string" || !obj.apiKey.trim()) {
79
+ throw new errors_1.ManagedConfigInvalidError("apiKey is required");
95
80
  }
96
81
  if (loadedFromPath !== paths_1.managedConfigPath) {
97
82
  // Best-effort migration to the new config filename.
98
83
  await promises_1.default.mkdir(paths_1.codexDir, { recursive: true });
99
84
  await promises_1.default.writeFile(paths_1.managedConfigPath, raw, "utf8").catch(() => { });
100
85
  }
101
- return {
102
- backendUrl,
103
- authType,
104
- seatId: obj.seatId,
105
- deviceToken: obj.deviceToken,
106
- apiKey: obj.apiKey,
107
- pollIntervalMs,
108
- };
86
+ return { backendUrl, apiKey: obj.apiKey.trim() };
109
87
  }
110
88
  async function writeManagedConfig(config) {
111
89
  if (typeof config.backendUrl !== "string" || !config.backendUrl.trim()) {
112
90
  throw new errors_1.ManagedConfigInvalidError("backendUrl is required");
113
91
  }
114
92
  const backendUrl = normalizeAndValidateBackendUrl(config.backendUrl);
115
- if (config.authType !== "seat" && config.authType !== "apiKey") {
116
- throw new errors_1.ManagedConfigInvalidError('authType must be "seat" or "apiKey"');
117
- }
118
- if (config.authType === "seat") {
119
- if (typeof config.seatId !== "string" || !config.seatId.trim()) {
120
- throw new errors_1.ManagedConfigInvalidError("seatId is required for authType=seat");
121
- }
122
- if (typeof config.deviceToken !== "string" || !config.deviceToken.trim()) {
123
- throw new errors_1.ManagedConfigInvalidError("deviceToken is required for authType=seat");
124
- }
125
- }
126
- else {
127
- if (typeof config.apiKey !== "string" || !config.apiKey.trim()) {
128
- throw new errors_1.ManagedConfigInvalidError("apiKey is required for authType=apiKey");
129
- }
93
+ if (typeof config.apiKey !== "string" || !config.apiKey.trim()) {
94
+ throw new errors_1.ManagedConfigInvalidError("apiKey is required");
130
95
  }
131
96
  await promises_1.default.mkdir(paths_1.codexDir, { recursive: true });
132
97
  const contents = JSON.stringify({
133
98
  backendUrl,
134
- authType: config.authType,
135
- seatId: config.seatId,
136
- deviceToken: config.deviceToken,
137
- apiKey: config.apiKey,
138
- pollIntervalMs: config.pollIntervalMs,
99
+ apiKey: config.apiKey.trim(),
139
100
  }, null, 2);
140
101
  await promises_1.default.writeFile(paths_1.managedConfigPath, `${contents}\n`, "utf8");
141
102
  }