theclawbay 0.3.3 → 0.3.5

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.
@@ -18,6 +18,7 @@ const errors_1 = require("../lib/managed/errors");
18
18
  const DEFAULT_BACKEND_URL = "https://theclawbay.com";
19
19
  const DEFAULT_PROVIDER_ID = "theclawbay";
20
20
  const LEGACY_PROVIDER_ID = "codex-lb";
21
+ const CLI_HTTP_USER_AGENT = "theclawbay-cli";
21
22
  const DEFAULT_CODEX_MODEL = "gpt-5.4";
22
23
  const DEFAULT_OPENCLAW_MODEL = "gpt-5.4";
23
24
  const DEFAULT_MODELS = ["gpt-5.4", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.2-codex", "gpt-5.1-codex"];
@@ -64,7 +65,8 @@ function normalizeUrl(raw, label) {
64
65
  }
65
66
  }
66
67
  function hasCommand(name) {
67
- const result = (0, node_child_process_1.spawnSync)("which", [name], { stdio: "ignore" });
68
+ const lookupCommand = node_os_1.default.platform() === "win32" ? "where.exe" : "which";
69
+ const result = (0, node_child_process_1.spawnSync)(lookupCommand, [name], { stdio: "ignore" });
68
70
  return result.status === 0;
69
71
  }
70
72
  function removeManagedBlock(source, start, end) {
@@ -124,7 +126,11 @@ async function fetchBackendModelIds(backendUrl, apiKey) {
124
126
  const url = `${trimTrailingSlash(backendUrl)}/api/codex-auth/v1/proxy/v1/models`;
125
127
  try {
126
128
  const response = await fetch(url, {
127
- headers: { Authorization: `Bearer ${apiKey}` },
129
+ headers: {
130
+ Authorization: `Bearer ${apiKey}`,
131
+ Accept: "application/json",
132
+ "User-Agent": CLI_HTTP_USER_AGENT,
133
+ },
128
134
  signal: AbortSignal.timeout(4500),
129
135
  });
130
136
  if (!response.ok)
@@ -9,9 +9,12 @@ const node_crypto_1 = require("node:crypto");
9
9
  const promises_1 = __importDefault(require("node:fs/promises"));
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
11
  const node_child_process_1 = require("node:child_process");
12
+ const node_os_1 = __importDefault(require("node:os"));
12
13
  const MODELS_CACHE_FILE = "models_cache.json";
13
14
  const MODELS_CACHE_STATE_FILE = "theclawbay.models-cache.json";
14
15
  const TARGET_MODEL_ID = "gpt-5.4";
16
+ const SEED_MARKER_KEY = "_theclawbay_seeded";
17
+ const SEED_MARKER_VALUE = "gpt-5.4";
15
18
  const TEMPLATE_MODEL_IDS = [
16
19
  "gpt-5.3-codex",
17
20
  "gpt-5.3-codex-spark",
@@ -119,8 +122,16 @@ async function writePatchState(statePath, fingerprint) {
119
122
  function findModel(models, slug) {
120
123
  return models.find((entry) => entry.slug === slug) ?? null;
121
124
  }
125
+ function hasSeedMarker(model) {
126
+ return model[SEED_MARKER_KEY] === SEED_MARKER_VALUE;
127
+ }
128
+ function applySeedMarker(model) {
129
+ const next = cloneJson(model);
130
+ next[SEED_MARKER_KEY] = SEED_MARKER_VALUE;
131
+ return next;
132
+ }
122
133
  function normalizeSeedModel(template) {
123
- const seed = cloneJson(template ?? {});
134
+ const seed = applySeedMarker(template ?? {});
124
135
  seed.slug = TARGET_MODEL_ID;
125
136
  seed.display_name = TARGET_MODEL_ID;
126
137
  seed.description = "Latest frontier agentic coding model.";
@@ -188,12 +199,26 @@ function parseCodexVersion(stdout) {
188
199
  const match = stdout.match(/\b(\d+\.\d+\.\d+)\b/);
189
200
  return match ? match[1] : null;
190
201
  }
202
+ function runVersionCommand(command, args) {
203
+ const run = (0, node_child_process_1.spawnSync)(command, args, {
204
+ encoding: "utf8",
205
+ stdio: ["ignore", "pipe", "pipe"],
206
+ });
207
+ if (run.status !== 0)
208
+ return null;
209
+ return parseCodexVersion(`${run.stdout ?? ""}\n${run.stderr ?? ""}`);
210
+ }
191
211
  function inferCodexClientVersion() {
212
+ if (node_os_1.default.platform() === "win32") {
213
+ for (const commandLine of ["codex --version", "codex-cli --version", "codex.cmd --version", "codex-cli.cmd --version"]) {
214
+ const parsed = runVersionCommand("cmd.exe", ["/d", "/s", "/c", commandLine]);
215
+ if (parsed)
216
+ return parsed;
217
+ }
218
+ return null;
219
+ }
192
220
  for (const command of ["codex", "codex-cli"]) {
193
- const run = (0, node_child_process_1.spawnSync)(command, ["--version"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
194
- if (run.status !== 0)
195
- continue;
196
- const parsed = parseCodexVersion(run.stdout ?? "");
221
+ const parsed = runVersionCommand(command, ["--version"]);
197
222
  if (parsed)
198
223
  return parsed;
199
224
  }
@@ -244,6 +269,19 @@ async function ensureCodexModelCacheHasGpt54(params) {
244
269
  const existingModel = findModel(doc.models, TARGET_MODEL_ID);
245
270
  if (existingModel) {
246
271
  const currentFingerprint = fingerprintModel(existingModel);
272
+ if (existingState && existingState.fingerprint === currentFingerprint && !hasSeedMarker(existingModel)) {
273
+ const seededModel = applySeedMarker(existingModel);
274
+ doc.models = doc.models.map((entry) => (entry.slug === TARGET_MODEL_ID ? seededModel : entry));
275
+ await promises_1.default.writeFile(cachePath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
276
+ await writePatchState(statePath, fingerprintModel(seededModel));
277
+ return { action: "seeded" };
278
+ }
279
+ if (hasSeedMarker(existingModel)) {
280
+ if (!existingState || existingState.fingerprint !== currentFingerprint) {
281
+ await writePatchState(statePath, currentFingerprint);
282
+ }
283
+ return { action: "already_seeded" };
284
+ }
247
285
  if (existingState && existingState.fingerprint !== currentFingerprint) {
248
286
  await removeFileIfExists(statePath);
249
287
  }
@@ -291,10 +329,17 @@ async function cleanupSeededCodexModelCache(params) {
291
329
  return { action: "none" };
292
330
  }
293
331
  const currentFingerprint = fingerprintModel(existingModel);
294
- if (currentFingerprint !== state.fingerprint) {
332
+ if (!hasSeedMarker(existingModel)) {
295
333
  await removeFileIfExists(statePath);
296
334
  return { action: "preserved" };
297
335
  }
336
+ if (currentFingerprint !== state.fingerprint) {
337
+ await writePatchState(statePath, currentFingerprint);
338
+ doc.models = doc.models.filter((entry) => entry.slug !== TARGET_MODEL_ID);
339
+ await promises_1.default.writeFile(cachePath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
340
+ await removeFileIfExists(statePath);
341
+ return { action: "removed" };
342
+ }
298
343
  doc.models = doc.models.filter((entry) => entry.slug !== TARGET_MODEL_ID);
299
344
  await promises_1.default.writeFile(cachePath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
300
345
  await removeFileIfExists(statePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theclawbay",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "The Claw Bay CLI: one-time API-key setup for direct Codex access.",
5
5
  "license": "MIT",
6
6
  "bin": {