theclawbay 0.3.70 → 0.3.72

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.
@@ -65,7 +65,7 @@ const LEGACY_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
65
65
  const CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/v1";
66
66
  const THECLAWBAY_CANONICAL_API_HOST = "api.theclawbay.com";
67
67
  const THECLAWBAY_WEBSITE_HOSTS = new Set(["theclawbay.com", "www.theclawbay.com"]);
68
- const SUPPORTED_MODEL_IDS = new Set((0, supported_models_1.getKnownTheClawBayModelIds)());
68
+ const SUPPORTED_MODEL_IDS = new Set((0, supported_models_1.getSupportedModelIds)());
69
69
  const CONTINUE_MODEL_NAME = "The Claw Bay";
70
70
  const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
71
71
  const TRAE_BUNDLE_BACKUP_SUFFIX = ".theclawbay-managed-backup";
@@ -1548,10 +1548,10 @@ class LogoutCommand extends base_command_1.BaseCommand {
1548
1548
  this.log("- Codex login state: no cleanup needed.");
1549
1549
  }
1550
1550
  if (modelCacheCleanup.action === "removed") {
1551
- this.log("- Codex model cache: removed the Claw Bay managed model catalog.");
1551
+ this.log("- Codex model cache: removed the Claw Bay GPT-5.5 / GPT-5.4 / GPT-5.4 Mini seed.");
1552
1552
  }
1553
1553
  else if (modelCacheCleanup.action === "preserved") {
1554
- this.log("- Codex model cache: preserved an existing model catalog entry.");
1554
+ this.log("- Codex model cache: preserved an existing GPT-5.5 / GPT-5.4 / GPT-5.4 Mini entry.");
1555
1555
  }
1556
1556
  else if (modelCacheCleanup.warning) {
1557
1557
  this.log(`- Codex model cache: ${modelCacheCleanup.warning}`);
@@ -14,7 +14,6 @@ const core_1 = require("@oclif/core");
14
14
  const yaml_1 = require("yaml");
15
15
  const base_command_1 = require("../lib/base-command");
16
16
  const codex_auth_seeding_1 = require("../lib/codex-auth-seeding");
17
- const codex_desktop_model_picker_1 = require("../lib/codex-desktop-model-picker");
18
17
  const codex_history_migration_1 = require("../lib/codex-history-migration");
19
18
  const codex_model_cache_migration_1 = require("../lib/codex-model-cache-migration");
20
19
  const paths_1 = require("../lib/config/paths");
@@ -28,9 +27,7 @@ const DEFAULT_PROVIDER_ID = "theclawbay";
28
27
  const CLI_HTTP_USER_AGENT = "theclawbay-cli";
29
28
  const SUPPORTED_MODEL_IDS = (0, supported_models_1.getSupportedModelIds)();
30
29
  const MODEL_DISPLAY_NAMES = (0, supported_models_1.getSupportedModelDisplayNames)();
31
- const DEFAULT_CODEX_MODEL = (["gpt-5.5", "gpt-5.4"].find((modelId) => SUPPORTED_MODEL_IDS.includes(modelId)) ??
32
- SUPPORTED_MODEL_IDS[0] ??
33
- "gpt-5.4");
30
+ const DEFAULT_CODEX_MODEL = SUPPORTED_MODEL_IDS[0] ?? "gpt-5.5";
34
31
  const DEFAULT_CONTINUE_MODEL = DEFAULT_CODEX_MODEL;
35
32
  const DEFAULT_CLINE_MODEL = DEFAULT_CODEX_MODEL;
36
33
  const DEFAULT_OPENCLAW_MODEL = DEFAULT_CODEX_MODEL;
@@ -40,7 +37,7 @@ const DEFAULT_TRAE_MODEL = DEFAULT_CODEX_MODEL;
40
37
  const DEFAULT_AIDER_MODEL = DEFAULT_CODEX_MODEL;
41
38
  const DEFAULT_ZO_MODEL = DEFAULT_CODEX_MODEL;
42
39
  const DEFAULT_MODELS = [...SUPPORTED_MODEL_IDS];
43
- const PREFERRED_MODELS = Array.from(new Set(["gpt-5.5", ...SUPPORTED_MODEL_IDS]));
40
+ const PREFERRED_MODELS = [...SUPPORTED_MODEL_IDS];
44
41
  const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
45
42
  const CLAUDE_ENV_API_KEY_NAME = "ANTHROPIC_API_KEY";
46
43
  const CLAUDE_ENV_BASE_URL_NAME = "ANTHROPIC_BASE_URL";
@@ -516,7 +513,10 @@ function upsertTopLevelTableKey(source, tableName, key, tomlValue) {
516
513
  lines.splice(tableEnd, 0, `${key} = ${tomlValue}`);
517
514
  return `${lines.join("\n").trimEnd()}\n`;
518
515
  }
519
- function readTopLevelTableKeyValue(source, tableName, key) {
516
+ function setTopLevelTableKey(source, tableName, key, tomlValue) {
517
+ return upsertTopLevelTableKey(source, tableName, key, tomlValue);
518
+ }
519
+ function removeTopLevelTableKey(source, tableName, key) {
520
520
  const header = `[${tableName}]`;
521
521
  const lines = source.split(/\r?\n/);
522
522
  let tableStart = -1;
@@ -526,20 +526,55 @@ function readTopLevelTableKeyValue(source, tableName, key) {
526
526
  break;
527
527
  }
528
528
  }
529
- if (tableStart < 0) {
530
- return { hadTable: false, hadKey: false, value: null };
531
- }
529
+ if (tableStart < 0)
530
+ return source;
531
+ let tableEnd = lines.length;
532
532
  for (let i = tableStart + 1; i < lines.length; i++) {
533
- const line = lines[i] ?? "";
534
- if (/^\s*\[[^\]]+\]\s*$/.test(line))
533
+ if (/^\s*\[[^\]]+\]\s*$/.test(lines[i] ?? "")) {
534
+ tableEnd = i;
535
535
  break;
536
- if (/^\s*#/.test(line) || !line.trim())
536
+ }
537
+ }
538
+ const nextLines = [...lines];
539
+ for (let i = tableStart + 1; i < tableEnd; i++) {
540
+ const line = nextLines[i] ?? "";
541
+ if (/^\s*#/.test(line))
537
542
  continue;
538
543
  if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
539
- return { hadTable: true, hadKey: true, value: parseTomlScalarValue(line) };
544
+ nextLines.splice(i, 1);
545
+ return `${nextLines.join("\n").trimEnd()}\n`;
540
546
  }
541
547
  }
542
- return { hadTable: true, hadKey: false, value: null };
548
+ return source;
549
+ }
550
+ async function restoreManagedCodexFeatureFlags(source) {
551
+ const snapshotRaw = await readFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
552
+ if (snapshotRaw === null || !snapshotRaw.trim())
553
+ return source;
554
+ let snapshot = null;
555
+ try {
556
+ snapshot = JSON.parse(snapshotRaw);
557
+ }
558
+ catch {
559
+ snapshot = null;
560
+ }
561
+ await removeFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
562
+ if (!snapshot)
563
+ return source;
564
+ let next = source;
565
+ if (snapshot.appsHadKey && snapshot.appsPreviousValue !== null) {
566
+ next = setTopLevelTableKey(next, "features", "apps", snapshot.appsPreviousValue);
567
+ }
568
+ else {
569
+ next = removeTopLevelTableKey(next, "features", "apps");
570
+ }
571
+ if (snapshot.appsMcpGatewayHadKey && snapshot.appsMcpGatewayPreviousValue !== null) {
572
+ next = setTopLevelTableKey(next, "features", "apps_mcp_gateway", snapshot.appsMcpGatewayPreviousValue);
573
+ }
574
+ else {
575
+ next = removeTopLevelTableKey(next, "features", "apps_mcp_gateway");
576
+ }
577
+ return next;
543
578
  }
544
579
  function removeTopLevelKeyLineIf(source, key, shouldRemove) {
545
580
  const lines = source.split(/\r?\n/);
@@ -1088,38 +1123,18 @@ function resolveSetupClientSelection(params) {
1088
1123
  async function promptForCodexConversationMigration() {
1089
1124
  if (!process.stdin.isTTY || !process.stdout.isTTY)
1090
1125
  return false;
1091
- const stdin = process.stdin;
1092
- const stdout = process.stdout;
1093
- const wasRaw = stdin.isRaw;
1094
- stdin.resume();
1095
- return new Promise((resolve) => {
1096
- const finish = (enabled) => {
1097
- stdin.off("data", onData);
1098
- if (stdin.isTTY)
1099
- stdin.setRawMode(Boolean(wasRaw));
1100
- stdout.write("\n");
1101
- resolve(enabled);
1102
- };
1103
- const onData = (chunk) => {
1104
- const key = chunk.toString("utf8");
1105
- if (key === "\u0003") {
1106
- stdout.write("\x1b[?25h");
1107
- process.exit(130);
1108
- }
1109
- const normalized = key.trim().toLowerCase();
1110
- if (normalized === "y" || normalized === "yes") {
1111
- finish(true);
1112
- return;
1113
- }
1114
- if (!normalized || normalized === "n" || normalized === "no") {
1115
- finish(false);
1116
- }
1117
- };
1118
- process.stdout.write("\nConvert old Codex conversations so they stay visible under The Claw Bay? [y/N] ");
1119
- if (stdin.isTTY)
1120
- stdin.setRawMode(true);
1121
- stdin.on("data", onData);
1126
+ const rl = (0, promises_2.createInterface)({
1127
+ input: process.stdin,
1128
+ output: process.stdout,
1122
1129
  });
1130
+ try {
1131
+ const answer = await rl.question("\nConvert old Codex conversations so they stay visible under The Claw Bay? [y/N] ");
1132
+ const normalized = answer.trim().toLowerCase();
1133
+ return normalized === "y" || normalized === "yes";
1134
+ }
1135
+ finally {
1136
+ rl.close();
1137
+ }
1123
1138
  }
1124
1139
  async function resolveCodexConversationMigrationSelection(params) {
1125
1140
  if (!params.codexSelected)
@@ -1509,36 +1524,15 @@ async function writeCodexConfig(params) {
1509
1524
  }
1510
1525
  const proxyRoot = publicApiOriginForBackendUrl(params.backendUrl);
1511
1526
  const nativeCodexBaseUrl = `${proxyRoot}${CANONICAL_CODEX_NATIVE_PROXY_SUFFIX}`;
1512
- let next = existing;
1527
+ let next = await restoreManagedCodexFeatureFlags(existing);
1513
1528
  next = removeManagedBlock(next, MANAGED_START, MANAGED_END);
1514
1529
  next = removeProviderTable(next, DEFAULT_PROVIDER_ID);
1515
- next = upsertFirstKeyLine(next, "model_provider", `"${DEFAULT_PROVIDER_ID}"`);
1530
+ next = upsertFirstKeyLine(next, "model_provider", `"${OPENAI_PROVIDER_ID}"`);
1516
1531
  next = upsertFirstKeyLine(next, "model", `"${params.model}"`);
1532
+ next = upsertFirstKeyLine(next, "openai_base_url", `"${nativeCodexBaseUrl}"`);
1517
1533
  next = removeTopLevelKeyLineIf(next, "chatgpt_base_url", isTheClawBayChatgptBaseUrl);
1518
- const existingFeatureSnapshot = await readFileIfExists(CODEX_FEATURE_FLAGS_STATE_PATH);
1519
- if (!existingFeatureSnapshot?.trim()) {
1520
- const appsState = readTopLevelTableKeyValue(next, "features", "apps");
1521
- const appsMcpGatewayState = readTopLevelTableKeyValue(next, "features", "apps_mcp_gateway");
1522
- const snapshot = {
1523
- hadFeaturesTable: appsState.hadTable || appsMcpGatewayState.hadTable,
1524
- appsHadKey: appsState.hadKey,
1525
- appsPreviousValue: appsState.value,
1526
- appsMcpGatewayHadKey: appsMcpGatewayState.hadKey,
1527
- appsMcpGatewayPreviousValue: appsMcpGatewayState.value,
1528
- };
1529
- await writeJsonObjectFile(CODEX_FEATURE_FLAGS_STATE_PATH, snapshot, 0o600);
1530
- }
1531
- next = upsertTopLevelTableKey(next, "features", "apps", "false");
1532
- next = upsertTopLevelTableKey(next, "features", "apps_mcp_gateway", "false");
1533
1534
  const managedBlock = appendManagedBlock("", [
1534
1535
  MANAGED_START,
1535
- `[model_providers.${DEFAULT_PROVIDER_ID}]`,
1536
- 'name = "OpenAI"',
1537
- `base_url = "${nativeCodexBaseUrl}"`,
1538
- 'wire_api = "responses"',
1539
- "requires_openai_auth = true",
1540
- "supports_websockets = true",
1541
- `experimental_bearer_token = "${params.apiKey}"`,
1542
1536
  MANAGED_END,
1543
1537
  ]);
1544
1538
  next = appendManagedBlock(next, managedBlock.trimEnd().split("\n"));
@@ -2417,12 +2411,10 @@ function objectRecordOr(value, fallback) {
2417
2411
  function modelContextLimit(modelId) {
2418
2412
  if (modelId === "gpt-5.4")
2419
2413
  return 1050000;
2420
- if (modelId === "gpt-5.5")
2421
- return 1000000;
2422
2414
  return 272000;
2423
2415
  }
2424
2416
  function modelOutputLimit(modelId) {
2425
- if (modelId === "gpt-5.4" || modelId === "gpt-5.5")
2417
+ if (modelId === "gpt-5.4")
2426
2418
  return 128000;
2427
2419
  return 65536;
2428
2420
  }
@@ -2989,10 +2981,9 @@ class SetupCommand extends base_command_1.BaseCommand {
2989
2981
  let restoredClaudeDesktop3pConfig = false;
2990
2982
  let claudeDesktop3pConfigPathManaged = null;
2991
2983
  let sessionMigration = null;
2992
- let authSeedResult = null;
2984
+ let authSeedCleanup = null;
2993
2985
  let stateDbMigration = null;
2994
2986
  let modelCacheMigration = null;
2995
- let desktopModelPickerMigration = null;
2996
2987
  let continueConfigPath = null;
2997
2988
  let clineConfigPaths = [];
2998
2989
  let gsdConfigPaths = [];
@@ -3092,22 +3083,19 @@ class SetupCommand extends base_command_1.BaseCommand {
3092
3083
  neutralizeSources: HISTORY_PROVIDER_NEUTRALIZE_SOURCES,
3093
3084
  });
3094
3085
  }
3095
- authSeedResult = await (0, codex_auth_seeding_1.ensureCodexUsageLimitAuth)({
3086
+ authSeedCleanup = await (0, codex_auth_seeding_1.cleanupSeededCodexAuth)({
3096
3087
  codexHome: paths_1.codexDir,
3097
- apiKey: authCredential,
3098
- replaceExistingAuth: true,
3099
3088
  });
3100
3089
  if (migrateCodexConversations) {
3101
3090
  stateDbMigration = await (0, codex_history_migration_1.migrateStateDbProviders)({
3102
3091
  codexHome: paths_1.codexDir,
3103
- targetProvider: DEFAULT_PROVIDER_ID,
3092
+ targetProvider: OPENAI_PROVIDER_ID,
3104
3093
  sourceProviders: HISTORY_PROVIDER_DB_MIGRATE_SOURCES,
3105
3094
  });
3106
3095
  }
3107
3096
  modelCacheMigration = await (0, codex_model_cache_migration_1.ensureCodexModelCacheHasGpt54)({
3108
3097
  codexHome: paths_1.codexDir,
3109
3098
  });
3110
- desktopModelPickerMigration = await (0, codex_desktop_model_picker_1.ensureCodexDesktopModelPickerSupport)();
3111
3099
  }
3112
3100
  if (selectedSetupClients.has("continue")) {
3113
3101
  progress.update("Configuring Continue");
@@ -3236,19 +3224,13 @@ class SetupCommand extends base_command_1.BaseCommand {
3236
3224
  }
3237
3225
  if (modelCacheMigration?.warning)
3238
3226
  summaryNotes.add(modelCacheMigration.warning);
3239
- if (desktopModelPickerMigration?.warning)
3240
- summaryNotes.add(desktopModelPickerMigration.warning);
3241
- if (authSeedResult?.warning)
3242
- summaryNotes.add(authSeedResult.warning);
3243
- if (authSeedResult &&
3244
- ["seeded", "updated", "already_seeded"].includes(authSeedResult.action)) {
3245
- summaryNotes.add("Codex desktop clients were pinned to the local The Claw Bay API-key auth path while the desktop picker compatibility patches keep current VS Code and Codex app builds on the The Claw Bay model catalog.");
3246
- }
3247
- if (desktopModelPickerMigration?.action === "patched") {
3248
- summaryNotes.add("Desktop model pickers were refreshed so current VS Code and Codex app builds stop labeling supported The Claw Bay models like GPT-5.5 as Custom.");
3227
+ if (authSeedCleanup?.warning)
3228
+ summaryNotes.add(authSeedCleanup.warning);
3229
+ if (authSeedCleanup?.action === "removed") {
3230
+ summaryNotes.add("Removed an older The Claw Bay Codex auth override that newer Codex releases now treat as invalid ChatGPT OAuth.");
3249
3231
  }
3250
- if (selectedSetupClients.has("codex")) {
3251
- summaryNotes.add("If Codex updates later, rerun `theclawbay setup` once to refresh its local model catalog.");
3232
+ else if (authSeedCleanup?.action === "restored_backup") {
3233
+ summaryNotes.add("Restored the Codex auth that existed before an older The Claw Bay auth override.");
3252
3234
  }
3253
3235
  if (selectedSetupClients.has("codex") && !migrateCodexConversations) {
3254
3236
  summaryNotes.add("Left existing Codex conversations untouched.");
@@ -3351,31 +3333,17 @@ class SetupCommand extends base_command_1.BaseCommand {
3351
3333
  else if (modelCacheMigration) {
3352
3334
  this.log("- Codex model cache: no change.");
3353
3335
  }
3354
- if (desktopModelPickerMigration?.action === "patched") {
3355
- this.log("- Codex desktop picker: refreshed VS Code / Codex app picker compatibility so supported The Claw Bay models keep their real labels.");
3356
- }
3357
- else if (desktopModelPickerMigration?.warning) {
3358
- this.log(`- Codex desktop picker: ${desktopModelPickerMigration.warning}`);
3359
- }
3360
- else if (desktopModelPickerMigration) {
3361
- this.log("- Codex desktop picker: no change.");
3362
- }
3363
- if (authSeedResult?.action === "seeded") {
3364
- this.log(authSeedResult.replacedExistingAuth
3365
- ? "- Codex login state: backed up the existing Codex auth and switched local desktop auth back to the Claw Bay API-key mode."
3366
- : "- Codex login state: seeded local desktop auth in the Claw Bay API-key mode.");
3367
- }
3368
- else if (authSeedResult?.action === "updated") {
3369
- this.log("- Codex login state: refreshed the local The Claw Bay API-key auth seed.");
3336
+ if (authSeedCleanup?.action === "restored_backup") {
3337
+ this.log("- Codex login state: restored the auth that existed before an older The Claw Bay override.");
3370
3338
  }
3371
- else if (authSeedResult?.action === "already_seeded") {
3372
- this.log("- Codex login state: local desktop auth was already pinned to the Claw Bay API-key mode.");
3339
+ else if (authSeedCleanup?.action === "removed") {
3340
+ this.log("- Codex login state: removed the older The Claw Bay ChatGPT-token override for compatibility with current Codex releases.");
3373
3341
  }
3374
- else if (authSeedResult?.warning) {
3375
- this.log(`- Codex login state: ${authSeedResult.warning}`);
3342
+ else if (authSeedCleanup?.warning) {
3343
+ this.log(`- Codex login state: ${authSeedCleanup.warning}`);
3376
3344
  }
3377
3345
  else {
3378
- this.log("- Codex login state: no change.");
3346
+ this.log("- Codex login state: using provider-scoped bearer auth only; no fake ChatGPT auth tokens were seeded.");
3379
3347
  }
3380
3348
  }
3381
3349
  else if (codexDetected) {
@@ -12,12 +12,10 @@ export type CleanupCodexAuthResult = {
12
12
  export declare function ensureCodexApiKeyAuth(params: {
13
13
  codexHome: string;
14
14
  apiKey: string;
15
- replaceExistingAuth?: boolean;
16
15
  }): Promise<EnsureCodexAuthResult>;
17
16
  export declare function ensureCodexUsageLimitAuth(params: {
18
17
  codexHome: string;
19
18
  apiKey: string;
20
- replaceExistingAuth?: boolean;
21
19
  }): Promise<EnsureCodexAuthResult>;
22
20
  export declare function cleanupSeededCodexAuth(params: {
23
21
  codexHome: string;
@@ -74,19 +74,15 @@ function buildFakeJwt(params) {
74
74
  }
75
75
  function buildSeededAuthDocument(params) {
76
76
  if (params.mode === "chatgpt-auth-tokens") {
77
- const fakeJwt = buildFakeJwt({
78
- email: THECLAWBAY_CHATGPT_EMAIL,
79
- accountId: THECLAWBAY_CHATGPT_ACCOUNT_ID,
80
- planType: THECLAWBAY_CHATGPT_PLAN_TYPE,
81
- });
82
77
  return {
83
78
  auth_mode: "chatgptAuthTokens",
84
79
  tokens: {
85
- // Current desktop Codex builds derive the local ChatGPT-style account
86
- // identity from these token fields. Keep them obviously fake so the real
87
- // The Claw Bay bearer stays scoped to experimental_bearer_token only.
88
- id_token: fakeJwt,
89
- access_token: fakeJwt,
80
+ id_token: buildFakeJwt({
81
+ email: THECLAWBAY_CHATGPT_EMAIL,
82
+ accountId: THECLAWBAY_CHATGPT_ACCOUNT_ID,
83
+ planType: THECLAWBAY_CHATGPT_PLAN_TYPE,
84
+ }),
85
+ access_token: params.apiKey,
90
86
  refresh_token: "",
91
87
  account_id: THECLAWBAY_CHATGPT_ACCOUNT_ID,
92
88
  },
@@ -240,16 +236,14 @@ async function ensureCodexApiKeyAuth(params) {
240
236
  codexHome: params.codexHome,
241
237
  apiKey: params.apiKey,
242
238
  mode: "api-key",
243
- replaceExistingAuth: params.replaceExistingAuth ?? false,
239
+ replaceExistingAuth: false,
244
240
  });
245
241
  }
246
242
  async function ensureCodexUsageLimitAuth(params) {
247
- // Current desktop Codex builds treat chatgptAuthTokens as real ChatGPT web
248
- // auth and can trigger upstream plugin sync calls against chatgpt.com. With
249
- // The Claw Bay, that can wedge the desktop startup path behind Cloudflare
250
- // challenges and leave Codex / VS Code stuck on splash. Keep desktop auth on
251
- // the local API-key path and rely on the managed config + picker patches for
252
- // model catalog compatibility instead.
243
+ // Current Codex releases treat chatgptAuthTokens.access_token as a real
244
+ // ChatGPT JWT and use it against chatgpt.com. The Claw Bay credentials are
245
+ // provider-scoped bearer tokens, so the legacy fake-ChatGPT seed path is no
246
+ // longer safe to apply here.
253
247
  return ensureCodexApiKeyAuth(params);
254
248
  }
255
249
  async function cleanupSeededCodexAuth(params) {