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.
- package/dist/commands/logout.js +57 -3
- package/dist/commands/setup.js +200 -17
- package/package.json +1 -1
package/dist/commands/logout.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 ||
|
|
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) {
|
package/dist/commands/setup.js
CHANGED
|
@@ -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
|
|
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 =
|
|
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 `${
|
|
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
|
-
|
|
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 = `${
|
|
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 =
|
|
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 = "${
|
|
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(
|
|
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
|
|
1407
|
+
const envLines = [
|
|
1294
1408
|
"# Generated by theclawbay setup",
|
|
1295
|
-
`export ${ENV_KEY_NAME}=${shellQuote(apiKey)}`,
|
|
1296
|
-
|
|
1297
|
-
|
|
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:
|
|
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 =
|
|
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 =
|
|
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(
|
|
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