theclawbay 0.3.46 → 0.3.48

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.
@@ -43,7 +43,10 @@ const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set([
43
43
  DEFAULT_PROVIDER_ID,
44
44
  ]);
45
45
  const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = [DEFAULT_PROVIDER_ID, WAN_PROVIDER_ID];
46
- const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
46
+ const LEGACY_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
47
+ const CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/v1";
48
+ const THECLAWBAY_CANONICAL_API_HOST = "api.theclawbay.com";
49
+ const THECLAWBAY_WEBSITE_HOSTS = new Set(["theclawbay.com", "www.theclawbay.com"]);
47
50
  const SUPPORTED_MODEL_IDS = new Set((0, supported_models_1.getSupportedModelIds)());
48
51
  const CONTINUE_MODEL_NAME = "The Claw Bay";
49
52
  const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
@@ -166,7 +169,28 @@ function objectRecordOr(value, fallback) {
166
169
  return fallback;
167
170
  }
168
171
  function isTheClawBayOpenAiCompatibleBaseUrl(value) {
169
- return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
172
+ if (typeof value !== "string")
173
+ return false;
174
+ const normalized = value.trim();
175
+ if (!normalized)
176
+ return false;
177
+ try {
178
+ const parsed = new URL(normalized);
179
+ const hostname = parsed.hostname.toLowerCase();
180
+ const pathname = parsed.pathname.replace(/\/+$/g, "");
181
+ if (pathname === LEGACY_THECLAWBAY_OPENAI_PROXY_SUFFIX &&
182
+ (THECLAWBAY_WEBSITE_HOSTS.has(hostname) ||
183
+ hostname === "localhost" ||
184
+ hostname === "127.0.0.1" ||
185
+ hostname === "::1")) {
186
+ return true;
187
+ }
188
+ return (hostname === THECLAWBAY_CANONICAL_API_HOST &&
189
+ pathname === CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX);
190
+ }
191
+ catch {
192
+ return false;
193
+ }
170
194
  }
171
195
  function uniqueStrings(values) {
172
196
  const output = [];
@@ -449,6 +473,27 @@ async function cleanupShellFiles() {
449
473
  }
450
474
  return updated;
451
475
  }
476
+ function powerShellProfilePaths() {
477
+ if (node_os_1.default.platform() !== "win32")
478
+ return [];
479
+ const home = node_os_1.default.homedir();
480
+ return [
481
+ node_path_1.default.join(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
482
+ node_path_1.default.join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
483
+ ];
484
+ }
485
+ async function cleanupPowerShellProfiles() {
486
+ const updated = [];
487
+ for (const profilePath of powerShellProfilePaths()) {
488
+ const existing = await readFileIfExists(profilePath);
489
+ if (existing === null)
490
+ continue;
491
+ const next = removeManagedBlock(existing, SHELL_START, SHELL_END);
492
+ if (await writeIfChanged(profilePath, next, existing))
493
+ updated.push(profilePath);
494
+ }
495
+ return updated;
496
+ }
452
497
  async function cleanupVsCodeHooks() {
453
498
  const updated = [];
454
499
  const homes = [".vscode-server", ".vscode-server-insiders"];
@@ -723,6 +768,7 @@ class LogoutCommand extends base_command_1.BaseCommand {
723
768
  let deletedManagedPaths = 0;
724
769
  let removedEnvFile = false;
725
770
  let updatedShellFiles = [];
771
+ let updatedPowerShellProfiles = [];
726
772
  let updatedVsCodeHooks = [];
727
773
  let updatedCodexConfig = false;
728
774
  let updatedContinueConfig = false;
@@ -770,6 +816,7 @@ class LogoutCommand extends base_command_1.BaseCommand {
770
816
  ])).filter(Boolean).length;
771
817
  removedEnvFile = await removeFileIfExists(ENV_FILE);
772
818
  updatedShellFiles = await cleanupShellFiles();
819
+ updatedPowerShellProfiles = await cleanupPowerShellProfiles();
773
820
  updatedVsCodeHooks = await cleanupVsCodeHooks();
774
821
  progress.update("Reverting Codex");
775
822
  updatedCodexConfig = await cleanupCodexConfig();
@@ -811,6 +858,8 @@ class LogoutCommand extends base_command_1.BaseCommand {
811
858
  throw error;
812
859
  }
813
860
  delete process.env[ENV_KEY_NAME];
861
+ delete process.env.ANTHROPIC_API_KEY;
862
+ delete process.env.ANTHROPIC_BASE_URL;
814
863
  if (!debugOutput && process.stdout.isTTY) {
815
864
  progress.succeed("Logout complete");
816
865
  }
@@ -861,7 +910,11 @@ class LogoutCommand extends base_command_1.BaseCommand {
861
910
  logLogoutCompactSummary({
862
911
  log: (message) => this.log(message),
863
912
  revertedTargets,
864
- sharedConfigChanged: deletedManagedPaths > 0 || removedEnvFile || updatedShellFiles.length > 0 || updatedVsCodeHooks.length > 0,
913
+ sharedConfigChanged: deletedManagedPaths > 0 ||
914
+ removedEnvFile ||
915
+ updatedShellFiles.length > 0 ||
916
+ updatedPowerShellProfiles.length > 0 ||
917
+ updatedVsCodeHooks.length > 0,
865
918
  notes: Array.from(summaryNotes),
866
919
  });
867
920
  return;
@@ -875,6 +928,7 @@ class LogoutCommand extends base_command_1.BaseCommand {
875
928
  this.log("- Remote device revoke: completed.");
876
929
  }
877
930
  this.log(`- Shell profiles updated: ${updatedShellFiles.length ? updatedShellFiles.join(", ") : "none"}`);
931
+ this.log(`- PowerShell profiles updated: ${updatedPowerShellProfiles.length ? updatedPowerShellProfiles.join(", ") : "none"}`);
878
932
  this.log(`- VS Code env hooks updated: ${updatedVsCodeHooks.length ? updatedVsCodeHooks.join(", ") : "none"}`);
879
933
  this.log(`- Codex config cleaned: ${updatedCodexConfig ? "yes" : "no"}`);
880
934
  if (sessionMigration.rewritten > 0) {
@@ -39,6 +39,8 @@ const DEFAULT_ZO_MODEL = DEFAULT_CODEX_MODEL;
39
39
  const DEFAULT_MODELS = [...SUPPORTED_MODEL_IDS];
40
40
  const PREFERRED_MODELS = [...SUPPORTED_MODEL_IDS];
41
41
  const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
42
+ const CLAUDE_ENV_API_KEY_NAME = "ANTHROPIC_API_KEY";
43
+ const CLAUDE_ENV_BASE_URL_NAME = "ANTHROPIC_BASE_URL";
42
44
  const ENV_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "env");
43
45
  const CONTINUE_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.yaml");
44
46
  const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "globalState.json");
@@ -60,7 +62,11 @@ const OPENCLAW_PROVIDER_ID = DEFAULT_PROVIDER_ID;
60
62
  const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set(["openai", "theclawbay-wan", DEFAULT_PROVIDER_ID]);
61
63
  const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = ["openai", "theclawbay-wan"];
62
64
  const SETUP_CLIENT_IDS = ["codex", "continue", "cline", "openclaw", "opencode", "kilo", "roo", "trae", "aider", "zo"];
63
- const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
65
+ const LEGACY_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
66
+ const CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX = "/v1";
67
+ const CANONICAL_CODEX_NATIVE_PROXY_SUFFIX = "/backend-api/codex";
68
+ const THECLAWBAY_CANONICAL_API_HOST = "api.theclawbay.com";
69
+ const THECLAWBAY_WEBSITE_HOSTS = new Set(["theclawbay.com", "www.theclawbay.com"]);
64
70
  const CONTINUE_MODEL_NAME = "The Claw Bay";
65
71
  const ROO_PROFILE_NAME = "The Claw Bay";
66
72
  const ROO_PROFILE_ID = "theclawbay-openai-compatible";
@@ -303,7 +309,7 @@ async function configureZoByok(params) {
303
309
  throw new Error("Zo was detected, but no active Zo desktop session token could be read. Open Zo, sign in, and rerun setup.");
304
310
  }
305
311
  const desiredName = `${ZO_CONFIG_NAME_PREFIX} ${modelDisplayName(params.model)}`;
306
- const desiredBaseUrl = `${trimTrailingSlash(params.backendUrl)}${THECLAWBAY_OPENAI_PROXY_SUFFIX}`;
312
+ const desiredBaseUrl = openAiCompatibleProxyUrl(params.backendUrl);
307
313
  const body = {
308
314
  provider: "openai-style",
309
315
  format: "openai",
@@ -446,14 +452,57 @@ function upsertFirstKeyLine(source, key, tomlValue) {
446
452
  function shellQuote(value) {
447
453
  return `'${value.replace(/'/g, `'\\''`)}'`;
448
454
  }
455
+ function powerShellQuote(value) {
456
+ return `'${value.replace(/'/g, "''")}'`;
457
+ }
449
458
  function modelDisplayName(modelId) {
450
459
  return MODEL_DISPLAY_NAMES[modelId] ?? modelId;
451
460
  }
461
+ function publicApiOriginForBackendUrl(backendUrl) {
462
+ const trimmed = trimTrailingSlash(backendUrl);
463
+ try {
464
+ const parsed = new URL(trimmed);
465
+ parsed.hash = "";
466
+ parsed.search = "";
467
+ parsed.pathname = "";
468
+ if (THECLAWBAY_WEBSITE_HOSTS.has(parsed.hostname.toLowerCase())) {
469
+ parsed.hostname = THECLAWBAY_CANONICAL_API_HOST;
470
+ }
471
+ return trimTrailingSlash(parsed.toString());
472
+ }
473
+ catch {
474
+ return trimmed;
475
+ }
476
+ }
452
477
  function openAiCompatibleProxyUrl(backendUrl) {
453
- return `${trimTrailingSlash(backendUrl)}${THECLAWBAY_OPENAI_PROXY_SUFFIX}`;
478
+ return `${publicApiOriginForBackendUrl(backendUrl)}${CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX}`;
479
+ }
480
+ function anthropicCompatibleProxyUrl(backendUrl) {
481
+ return `${publicApiOriginForBackendUrl(backendUrl)}/anthropic`;
454
482
  }
455
483
  function isTheClawBayOpenAiCompatibleBaseUrl(value) {
456
- return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
484
+ if (typeof value !== "string")
485
+ return false;
486
+ const normalized = value.trim();
487
+ if (!normalized)
488
+ return false;
489
+ try {
490
+ const parsed = new URL(normalized);
491
+ const hostname = parsed.hostname.toLowerCase();
492
+ const pathname = trimTrailingSlash(parsed.pathname);
493
+ if (pathname === LEGACY_THECLAWBAY_OPENAI_PROXY_SUFFIX &&
494
+ (THECLAWBAY_WEBSITE_HOSTS.has(hostname) ||
495
+ hostname === "localhost" ||
496
+ hostname === "127.0.0.1" ||
497
+ hostname === "::1")) {
498
+ return true;
499
+ }
500
+ return (hostname === THECLAWBAY_CANONICAL_API_HOST &&
501
+ pathname === CANONICAL_THECLAWBAY_OPENAI_PROXY_SUFFIX);
502
+ }
503
+ catch {
504
+ return false;
505
+ }
457
506
  }
458
507
  function uniqueStrings(values) {
459
508
  const output = [];
@@ -922,7 +971,7 @@ function summarizeModelFetchFailure(detail) {
922
971
  return `${normalized.slice(0, 137).trimEnd()}...`;
923
972
  }
924
973
  async function fetchBackendModelIds(backendUrl, apiKey) {
925
- const url = `${trimTrailingSlash(backendUrl)}/api/codex-auth/v1/proxy/v1/models`;
974
+ const url = `${openAiCompatibleProxyUrl(backendUrl)}/models`;
926
975
  try {
927
976
  const response = await fetch(url, {
928
977
  headers: {
@@ -971,6 +1020,56 @@ async function fetchBackendModelIds(backendUrl, apiKey) {
971
1020
  };
972
1021
  }
973
1022
  }
1023
+ async function fetchClaudeModelIds(backendUrl, apiKey) {
1024
+ const url = `${anthropicCompatibleProxyUrl(backendUrl)}/v1/models`;
1025
+ try {
1026
+ const response = await fetch(url, {
1027
+ headers: {
1028
+ "x-api-key": apiKey,
1029
+ Accept: "application/json",
1030
+ "User-Agent": CLI_HTTP_USER_AGENT,
1031
+ },
1032
+ signal: AbortSignal.timeout(10000),
1033
+ });
1034
+ if (!response.ok) {
1035
+ const responseText = await response.text().catch(() => "");
1036
+ let detail = responseText.trim();
1037
+ try {
1038
+ const parsed = JSON.parse(responseText);
1039
+ if (typeof parsed.error === "string" && parsed.error.trim()) {
1040
+ detail = parsed.error.trim();
1041
+ }
1042
+ else if (typeof parsed.code === "string" && parsed.code.trim()) {
1043
+ detail = parsed.code.trim();
1044
+ }
1045
+ }
1046
+ catch {
1047
+ // Keep the raw response text when the body is not JSON.
1048
+ }
1049
+ return {
1050
+ ids: null,
1051
+ failure: `HTTP ${response.status}${detail ? `: ${summarizeModelFetchFailure(detail)}` : ""}`,
1052
+ };
1053
+ }
1054
+ const body = (await response.json());
1055
+ const ids = (body.data ?? [])
1056
+ .map((entry) => (typeof entry.id === "string" ? entry.id.trim() : ""))
1057
+ .filter((id) => id.length > 0);
1058
+ if (!ids.length) {
1059
+ return {
1060
+ ids: null,
1061
+ failure: "backend returned an empty Claude model list",
1062
+ };
1063
+ }
1064
+ return { ids };
1065
+ }
1066
+ catch (error) {
1067
+ return {
1068
+ ids: null,
1069
+ failure: summarizeModelFetchFailure(error instanceof Error ? error.message : String(error)),
1070
+ };
1071
+ }
1072
+ }
974
1073
  function kiloStorageCandidates() {
975
1074
  const home = node_os_1.default.homedir();
976
1075
  const candidates = [node_path_1.default.join(home, ".config", "kilo"), node_path_1.default.join(home, ".kilo")];
@@ -1113,6 +1212,20 @@ async function resolveModels(backendUrl, apiKey) {
1113
1212
  note,
1114
1213
  };
1115
1214
  }
1215
+ async function resolveClaudeAccess(backendUrl, apiKey) {
1216
+ const { ids, failure } = await fetchClaudeModelIds(backendUrl, apiKey);
1217
+ if (!ids?.length) {
1218
+ return {
1219
+ enabled: false,
1220
+ models: [],
1221
+ note: failure ? `Claude Code auto-setup skipped (${failure}).` : undefined,
1222
+ };
1223
+ }
1224
+ return {
1225
+ enabled: true,
1226
+ models: ids,
1227
+ };
1228
+ }
1116
1229
  async function writeCodexConfig(params) {
1117
1230
  const configPath = node_path_1.default.join(paths_1.codexDir, "config.toml");
1118
1231
  await promises_1.default.mkdir(paths_1.codexDir, { recursive: true });
@@ -1125,7 +1238,8 @@ async function writeCodexConfig(params) {
1125
1238
  if (err.code !== "ENOENT")
1126
1239
  throw error;
1127
1240
  }
1128
- const proxyRoot = `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy`;
1241
+ const proxyRoot = publicApiOriginForBackendUrl(params.backendUrl);
1242
+ const nativeCodexBaseUrl = `${proxyRoot}${CANONICAL_CODEX_NATIVE_PROXY_SUFFIX}`;
1129
1243
  let next = existing;
1130
1244
  next = removeManagedBlock(next, MANAGED_START, MANAGED_END);
1131
1245
  next = removeProviderTable(next, DEFAULT_PROVIDER_ID);
@@ -1136,7 +1250,7 @@ async function writeCodexConfig(params) {
1136
1250
  MANAGED_START,
1137
1251
  `[model_providers.${DEFAULT_PROVIDER_ID}]`,
1138
1252
  'name = "OpenAI"',
1139
- `base_url = "${proxyRoot}/backend-api/codex"`,
1253
+ `base_url = "${nativeCodexBaseUrl}"`,
1140
1254
  'wire_api = "responses"',
1141
1255
  "requires_openai_auth = true",
1142
1256
  "supports_websockets = true",
@@ -1287,14 +1401,17 @@ async function writeAiderConfig(params) {
1287
1401
  await promises_1.default.writeFile(AIDER_CONFIG_PATH, next, "utf8");
1288
1402
  return AIDER_CONFIG_PATH;
1289
1403
  }
1290
- async function persistApiKeyEnv(apiKey) {
1404
+ async function persistApiKeyEnv(params) {
1291
1405
  const envDir = node_path_1.default.dirname(ENV_FILE);
1292
1406
  await promises_1.default.mkdir(envDir, { recursive: true });
1293
- const envContents = [
1407
+ const envLines = [
1294
1408
  "# Generated by theclawbay setup",
1295
- `export ${ENV_KEY_NAME}=${shellQuote(apiKey)}`,
1296
- "",
1297
- ].join("\n");
1409
+ `export ${ENV_KEY_NAME}=${shellQuote(params.apiKey)}`,
1410
+ ];
1411
+ if (params.claudeEnabled) {
1412
+ envLines.push("", "# Official Claude Code CLI", `export ${CLAUDE_ENV_API_KEY_NAME}=${shellQuote(params.apiKey)}`, `export ${CLAUDE_ENV_BASE_URL_NAME}=${shellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`);
1413
+ }
1414
+ const envContents = `${envLines.join("\n")}\n`;
1298
1415
  await promises_1.default.writeFile(ENV_FILE, envContents, "utf8");
1299
1416
  await promises_1.default.chmod(ENV_FILE, 0o600);
1300
1417
  const sourceLine = `[ -f "$HOME/.config/theclawbay/env" ] && . "$HOME/.config/theclawbay/env"`;
@@ -1315,7 +1432,44 @@ async function persistApiKeyEnv(apiKey) {
1315
1432
  await promises_1.default.writeFile(rcPath, withBlock, "utf8");
1316
1433
  updated.push(rcPath);
1317
1434
  }
1318
- process.env[ENV_KEY_NAME] = apiKey;
1435
+ process.env[ENV_KEY_NAME] = params.apiKey;
1436
+ if (params.claudeEnabled) {
1437
+ process.env[CLAUDE_ENV_API_KEY_NAME] = params.apiKey;
1438
+ process.env[CLAUDE_ENV_BASE_URL_NAME] = anthropicCompatibleProxyUrl(params.backendUrl);
1439
+ }
1440
+ else {
1441
+ delete process.env[CLAUDE_ENV_API_KEY_NAME];
1442
+ delete process.env[CLAUDE_ENV_BASE_URL_NAME];
1443
+ }
1444
+ return updated;
1445
+ }
1446
+ function powerShellProfilePaths() {
1447
+ if (node_os_1.default.platform() !== "win32")
1448
+ return [];
1449
+ const home = node_os_1.default.homedir();
1450
+ return [
1451
+ node_path_1.default.join(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
1452
+ node_path_1.default.join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
1453
+ ];
1454
+ }
1455
+ async function persistPowerShellEnv(params) {
1456
+ const updated = [];
1457
+ for (const profilePath of powerShellProfilePaths()) {
1458
+ await promises_1.default.mkdir(node_path_1.default.dirname(profilePath), { recursive: true });
1459
+ const existing = (await readFileIfExists(profilePath)) ?? "";
1460
+ const cleaned = removeManagedBlock(existing, SHELL_START, SHELL_END);
1461
+ const lines = [
1462
+ SHELL_START,
1463
+ `$env:${ENV_KEY_NAME} = ${powerShellQuote(params.apiKey)}`,
1464
+ ];
1465
+ if (params.claudeEnabled) {
1466
+ lines.push(`$env:${CLAUDE_ENV_API_KEY_NAME} = ${powerShellQuote(params.apiKey)}`, `$env:${CLAUDE_ENV_BASE_URL_NAME} = ${powerShellQuote(anthropicCompatibleProxyUrl(params.backendUrl))}`);
1467
+ }
1468
+ lines.push(SHELL_END);
1469
+ const next = appendManagedBlock(cleaned, lines);
1470
+ await promises_1.default.writeFile(profilePath, next, "utf8");
1471
+ updated.push(profilePath);
1472
+ }
1319
1473
  return updated;
1320
1474
  }
1321
1475
  async function persistVsCodeServerEnvSource() {
@@ -1371,7 +1525,7 @@ function resolveOpenClawPrimaryModel(params) {
1371
1525
  }
1372
1526
  async function patchOpenClawConfigFile(params) {
1373
1527
  const provider = {
1374
- baseUrl: `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`,
1528
+ baseUrl: openAiCompatibleProxyUrl(params.backendUrl),
1375
1529
  apiKey: params.apiKey,
1376
1530
  api: "openai-responses",
1377
1531
  models: buildOpenClawModels(params.models),
@@ -1684,7 +1838,7 @@ async function writeOpenCodeFamilyConfig(params) {
1684
1838
  }
1685
1839
  const managedOpenAiProvider = objectRecordOr(providerRoot[OPENAI_PROVIDER_ID], {});
1686
1840
  const optionsRoot = objectRecordOr(managedOpenAiProvider.options, {});
1687
- optionsRoot.baseURL = `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`;
1841
+ optionsRoot.baseURL = openAiCompatibleProxyUrl(params.backendUrl);
1688
1842
  optionsRoot.apiKey = params.apiKey;
1689
1843
  managedOpenAiProvider.options = optionsRoot;
1690
1844
  managedOpenAiProvider.models = buildOpenCodeModelsObject(params.models);
@@ -1726,7 +1880,7 @@ function traePatchSnippet(params) {
1726
1880
  const patchedModels = params.models.length
1727
1881
  ? params.models
1728
1882
  : [{ id: params.model.trim() || DEFAULT_TRAE_MODEL, name: modelDisplayName(params.model.trim() || DEFAULT_TRAE_MODEL) }];
1729
- const proxyBaseUrl = `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`;
1883
+ const proxyBaseUrl = openAiCompatibleProxyUrl(params.backendUrl);
1730
1884
  return `async setOriginModelListMapAndCache(e,t=!0){let{userProfile:r}=this.credentialStore.getState(),i=r?.scope!==v9.BYTEDANCE,n={},o=${JSON.stringify(patchedModels)};Object.keys(e).forEach(t=>{let r=[...(e[t]||[])],s=r[0]&&"object"==typeof r[0]?r[0]:null;if([Mh.Builder,Mh.SoloCoder].includes(t)&&s){let a=o.map((e,l)=>{let o={...s};return o.id=${JSON.stringify(TRAE_PATCH_MARKER)}+"-"+t+"-"+e.id,o.name=e.id,o.display_name=e.name,o.provider="theclawbay",o.icon={dark:"https://theclawbay.com/favicon.ico",light:"https://theclawbay.com/favicon.ico"},o.ak=${JSON.stringify(params.apiKey)},o.base_url=${JSON.stringify(proxyBaseUrl)},o.is_custom_base_url=!0,o.custom_model_id=${JSON.stringify(TRAE_PATCH_MARKER)}+"-"+e.id,o.selectable=!0,o.status=!0,o.is_default=0===l,o.config_source=MK.Personal,o.model_type=s.model_type??"chat_model",o.builder=s.builder??null,o.client_connect=!0,o.multimodal=!1!==s.multimodal,o.tags=Array.isArray(s.tags)?s.tags:[],o.auth_type="number"==typeof s.auth_type?s.auth_type:0,o.region=s.region??null,o.max_turns=s.max_turns??{default:50,max:50},o.context_window_size=s.context_window_size??{max:[128000],default:64000},o.features=s.features??{memory:{enable:!1},cost:{enable:!1,data:{manual_usage:0}},multimodal:{enable:!0},context_windows:{enable:!0,data:{dev_context:64000,max_context:128000,max_context_list:[128000],dev_turns:50,max_turns:50}}},o.commercial_info=s.commercial_info??{manual_usage:0,info:""},o.saas_usage=s.saas_usage??{max:0,default:null},o});n[t]=a;return}!i&&[Mh.SoloCoder,Mh.UIBuilder].includes(t)?n[t]=r?.filter(e=>e.config_source!==MK.Personal)||[]:n[t]=r}),this._modelStore.actions.setOriginModelListMap(n),t&&this._modelStorageService.storeModelListMap(n),this._logService.info("[ModelService.setOriginModelListMapAndCache] officialModels",Object.entries(n).map(([e,t])=>({scene:e,models:(t||[]).map(e=>e.display_name||e.name)})))}`;
1731
1885
  }
1732
1886
  async function patchTraeBundle(params) {
@@ -1932,7 +2086,9 @@ class SetupCommand extends base_command_1.BaseCommand {
1932
2086
  }
1933
2087
  const progress = this.createProgressHandle(!debugOutput);
1934
2088
  let resolved = null;
2089
+ let claudeAccess = null;
1935
2090
  let updatedShellFiles = [];
2091
+ let updatedPowerShellProfiles = [];
1936
2092
  let codexConfigPath = null;
1937
2093
  let updatedVsCodeEnvFiles = [];
1938
2094
  let sessionMigration = null;
@@ -1955,6 +2111,8 @@ class SetupCommand extends base_command_1.BaseCommand {
1955
2111
  progress.update("Resolving supported models");
1956
2112
  resolved = await resolveModels(backendUrl, authCredential);
1957
2113
  }
2114
+ progress.update("Checking Claude access");
2115
+ claudeAccess = await resolveClaudeAccess(backendUrl, authCredential);
1958
2116
  progress.update("Saving shared machine config");
1959
2117
  await (0, config_1.writeManagedConfig)({
1960
2118
  backendUrl,
@@ -1963,7 +2121,16 @@ class SetupCommand extends base_command_1.BaseCommand {
1963
2121
  deviceSessionId,
1964
2122
  deviceLabel,
1965
2123
  });
1966
- updatedShellFiles = await persistApiKeyEnv(authCredential);
2124
+ updatedShellFiles = await persistApiKeyEnv({
2125
+ apiKey: authCredential,
2126
+ backendUrl,
2127
+ claudeEnabled: claudeAccess.enabled,
2128
+ });
2129
+ updatedPowerShellProfiles = await persistPowerShellEnv({
2130
+ apiKey: authCredential,
2131
+ backendUrl,
2132
+ claudeEnabled: claudeAccess.enabled,
2133
+ });
1967
2134
  if (selectedSetupClients.has("codex")) {
1968
2135
  progress.update("Configuring Codex");
1969
2136
  codexConfigPath = await writeCodexConfig({
@@ -2089,6 +2256,13 @@ class SetupCommand extends base_command_1.BaseCommand {
2089
2256
  const summaryNotes = new Set();
2090
2257
  if (resolved?.note)
2091
2258
  summaryNotes.add(resolved.note);
2259
+ if (claudeAccess?.enabled) {
2260
+ summaryNotes.add("Claude Code: exported ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY for the official client.");
2261
+ summaryNotes.add("Claude Code may still show your claude.ai login in `claude auth status`. Restart Claude Code and approve `Use custom API key` if prompted, or enable it in `/config`.");
2262
+ }
2263
+ else if (claudeAccess?.note) {
2264
+ summaryNotes.add(claudeAccess.note);
2265
+ }
2092
2266
  if (selectedSetupClients.has("trae")) {
2093
2267
  summaryNotes.add("Trae uses an experimental patch. Restart Trae and pick a The Claw Bay model to test it.");
2094
2268
  }
@@ -2138,8 +2312,17 @@ class SetupCommand extends base_command_1.BaseCommand {
2138
2312
  }
2139
2313
  if (resolved?.note)
2140
2314
  this.log(resolved.note);
2315
+ if (claudeAccess?.enabled) {
2316
+ this.log(`- Claude Code base URL: ${anthropicCompatibleProxyUrl(backendUrl)}`);
2317
+ }
2318
+ else if (claudeAccess?.note) {
2319
+ this.log(`- Claude Code: ${claudeAccess.note}`);
2320
+ }
2141
2321
  this.log(`- Local credential env: ${ENV_FILE}`);
2142
2322
  this.log(`- Shell profiles updated: ${updatedShellFiles.join(", ")}`);
2323
+ if (updatedPowerShellProfiles.length > 0) {
2324
+ this.log(`- PowerShell profiles updated: ${updatedPowerShellProfiles.join(", ")}`);
2325
+ }
2143
2326
  if (selectedSetupClients.has("codex")) {
2144
2327
  this.log(`- Codex: configured (${codexConfigPath})`);
2145
2328
  if (resolved)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theclawbay",
3
- "version": "0.3.46",
3
+ "version": "0.3.48",
4
4
  "description": "CLI for connecting Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, experimental Trae, and experimental Zo to The Claw Bay.",
5
5
  "license": "MIT",
6
6
  "bin": {