codexui-android 0.1.81 → 0.1.83
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/README.md +10 -1
- package/dist/assets/{ReviewPane-Dee4Qknm.js → ReviewPane-nTMVVMpp.js} +2 -2
- package/dist/assets/{ReviewPane-Dee4Qknm.js.map → ReviewPane-nTMVVMpp.js.map} +1 -1
- package/dist/assets/{SkillsHub-DUNP6fA0.js → SkillsHub-BqjWaUSP.js} +2 -2
- package/dist/assets/{SkillsHub-DUNP6fA0.js.map → SkillsHub-BqjWaUSP.js.map} +1 -1
- package/dist/assets/{ThreadConversation-DlVMY4f_.js → ThreadConversation-Ctw55jX6.js} +2 -2
- package/dist/assets/{ThreadConversation-DlVMY4f_.js.map → ThreadConversation-Ctw55jX6.js.map} +1 -1
- package/dist/assets/index-BEf3759i.js +92 -0
- package/dist/assets/index-BEf3759i.js.map +1 -0
- package/dist/assets/index-iN-aqOuT.css +1 -0
- package/dist/index.html +2 -2
- package/dist-cli/{chunk-BEXSKX6U.js → chunk-UUZOL7SL.js} +43 -33
- package/dist-cli/chunk-UUZOL7SL.js.map +1 -0
- package/dist-cli/index.js +442 -10
- package/dist-cli/index.js.map +1 -1
- package/dist-cli/instrument.js +1 -1
- package/package.json +1 -1
- package/dist/assets/index-BjPXEYO9.js +0 -89
- package/dist/assets/index-BjPXEYO9.js.map +0 -1
- package/dist/assets/index-H9Lygcy8.css +0 -1
- package/dist-cli/chunk-BEXSKX6U.js.map +0 -1
package/dist-cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-UUZOL7SL.js";
|
|
3
3
|
|
|
4
4
|
// src/cli/index.ts
|
|
5
5
|
import { createServer as createServer2 } from "http";
|
|
@@ -227,7 +227,7 @@ import * as Sentry4 from "@sentry/node";
|
|
|
227
227
|
import { spawn as spawn4 } from "child_process";
|
|
228
228
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
229
229
|
import { mkdtemp as mkdtemp3, readFile as readFile3, rm as rm4, mkdir as mkdir4, stat as stat4 } from "fs/promises";
|
|
230
|
-
import { createReadStream } from "fs";
|
|
230
|
+
import { createReadStream, readFileSync } from "fs";
|
|
231
231
|
import { request as httpRequest } from "http";
|
|
232
232
|
import { request as httpsRequest } from "https";
|
|
233
233
|
import { homedir as homedir4 } from "os";
|
|
@@ -3141,8 +3141,27 @@ function getErrorMessage4(payload, fallback) {
|
|
|
3141
3141
|
}
|
|
3142
3142
|
return fallback;
|
|
3143
3143
|
}
|
|
3144
|
+
function normalizeTelegramAllowlist(values) {
|
|
3145
|
+
const rawValues = Array.isArray(values) ? values : [];
|
|
3146
|
+
const allowAllUsers = rawValues.some((value) => typeof value === "string" && value.trim() === "*");
|
|
3147
|
+
const allowedUserIds = Array.from(new Set(rawValues.map((value) => {
|
|
3148
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
3149
|
+
return Math.trunc(value);
|
|
3150
|
+
}
|
|
3151
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
3152
|
+
const normalized = value.trim().replace(/^(telegram|tg):/i, "").trim();
|
|
3153
|
+
if (/^-?\d+$/.test(normalized)) {
|
|
3154
|
+
return Number.parseInt(normalized, 10);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
return Number.NaN;
|
|
3158
|
+
}).filter((value) => Number.isFinite(value)))).slice(0, 100);
|
|
3159
|
+
return { allowAllUsers, allowedUserIds };
|
|
3160
|
+
}
|
|
3144
3161
|
var TelegramThreadBridge = class {
|
|
3145
3162
|
constructor(appServer, options = {}) {
|
|
3163
|
+
this.allowAllUsers = false;
|
|
3164
|
+
this.allowedUserIds = /* @__PURE__ */ new Set();
|
|
3146
3165
|
this.threadIdByChatId = /* @__PURE__ */ new Map();
|
|
3147
3166
|
this.chatIdsByThreadId = /* @__PURE__ */ new Map();
|
|
3148
3167
|
this.lastForwardedTurnByThreadId = /* @__PURE__ */ new Map();
|
|
@@ -3153,6 +3172,9 @@ var TelegramThreadBridge = class {
|
|
|
3153
3172
|
this.appServer = appServer;
|
|
3154
3173
|
this.token = process.env.TELEGRAM_BOT_TOKEN?.trim() ?? "";
|
|
3155
3174
|
this.defaultCwd = process.env.TELEGRAM_DEFAULT_CWD?.trim() ?? process.cwd();
|
|
3175
|
+
this.configureAllowedUserIds(
|
|
3176
|
+
(process.env.TELEGRAM_ALLOWED_USER_IDS ?? "").split(",").map((value) => value.trim()).filter(Boolean)
|
|
3177
|
+
);
|
|
3156
3178
|
this.onChatSeen = options.onChatSeen;
|
|
3157
3179
|
}
|
|
3158
3180
|
start() {
|
|
@@ -3220,9 +3242,16 @@ var TelegramThreadBridge = class {
|
|
|
3220
3242
|
active: this.active,
|
|
3221
3243
|
mappedChats: this.threadIdByChatId.size,
|
|
3222
3244
|
mappedThreads: this.chatIdsByThreadId.size,
|
|
3245
|
+
allowedUsers: this.allowedUserIds.size,
|
|
3246
|
+
allowAllUsers: this.allowAllUsers,
|
|
3223
3247
|
lastError: this.lastError
|
|
3224
3248
|
};
|
|
3225
3249
|
}
|
|
3250
|
+
configureAllowedUserIds(allowedUserIds) {
|
|
3251
|
+
const normalized = normalizeTelegramAllowlist(allowedUserIds);
|
|
3252
|
+
this.allowAllUsers = normalized.allowAllUsers;
|
|
3253
|
+
this.allowedUserIds = new Set(normalized.allowedUserIds);
|
|
3254
|
+
}
|
|
3226
3255
|
connectThread(threadId, chatId, token) {
|
|
3227
3256
|
const normalizedThreadId = threadId.trim();
|
|
3228
3257
|
if (!normalizedThreadId) {
|
|
@@ -3276,8 +3305,13 @@ var TelegramThreadBridge = class {
|
|
|
3276
3305
|
}
|
|
3277
3306
|
const message = update.message;
|
|
3278
3307
|
const chatId = message?.chat?.id;
|
|
3308
|
+
const senderId = message?.from?.id;
|
|
3279
3309
|
const text = message?.text?.trim();
|
|
3280
3310
|
if (typeof chatId !== "number" || !text) return;
|
|
3311
|
+
if (!this.isAllowedSender(senderId)) {
|
|
3312
|
+
await this.sendTelegramMessage(chatId, this.unauthorizedMessage(senderId));
|
|
3313
|
+
return;
|
|
3314
|
+
}
|
|
3281
3315
|
this.markChatSeen(chatId);
|
|
3282
3316
|
if (text === "/start") {
|
|
3283
3317
|
await this.sendThreadPicker(chatId);
|
|
@@ -3310,6 +3344,16 @@ var TelegramThreadBridge = class {
|
|
|
3310
3344
|
const callbackId = typeof callbackQuery.id === "string" ? callbackQuery.id : "";
|
|
3311
3345
|
const data = typeof callbackQuery.data === "string" ? callbackQuery.data : "";
|
|
3312
3346
|
const chatId = callbackQuery.message?.chat?.id;
|
|
3347
|
+
const senderId = callbackQuery.from?.id;
|
|
3348
|
+
if (!this.isAllowedSender(senderId)) {
|
|
3349
|
+
if (callbackId) {
|
|
3350
|
+
await this.answerCallbackQuery(callbackId, this.unauthorizedCallbackMessage(senderId));
|
|
3351
|
+
}
|
|
3352
|
+
if (typeof chatId === "number") {
|
|
3353
|
+
await this.sendTelegramMessage(chatId, this.unauthorizedMessage(senderId));
|
|
3354
|
+
}
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3313
3357
|
if (typeof chatId === "number") {
|
|
3314
3358
|
this.markChatSeen(chatId);
|
|
3315
3359
|
}
|
|
@@ -3331,6 +3375,25 @@ var TelegramThreadBridge = class {
|
|
|
3331
3375
|
await this.sendTelegramMessage(chatId, history);
|
|
3332
3376
|
}
|
|
3333
3377
|
}
|
|
3378
|
+
isAllowedSender(senderId) {
|
|
3379
|
+
if (this.allowAllUsers) {
|
|
3380
|
+
return typeof senderId === "number" && Number.isFinite(senderId);
|
|
3381
|
+
}
|
|
3382
|
+
return typeof senderId === "number" && Number.isFinite(senderId) && this.allowedUserIds.has(Math.trunc(senderId));
|
|
3383
|
+
}
|
|
3384
|
+
unauthorizedMessage(senderId) {
|
|
3385
|
+
const normalizedSenderId = typeof senderId === "number" && Number.isFinite(senderId) ? String(Math.trunc(senderId)) : "unknown";
|
|
3386
|
+
return `Unauthorized sender.
|
|
3387
|
+
|
|
3388
|
+
Your Telegram user ID: ${normalizedSenderId}
|
|
3389
|
+
Add this ID to the bot allowlist before using the bridge.`;
|
|
3390
|
+
}
|
|
3391
|
+
unauthorizedCallbackMessage(senderId) {
|
|
3392
|
+
if (typeof senderId === "number" && Number.isFinite(senderId)) {
|
|
3393
|
+
return `Unauthorized: ${String(Math.trunc(senderId))}`;
|
|
3394
|
+
}
|
|
3395
|
+
return "Unauthorized sender";
|
|
3396
|
+
}
|
|
3334
3397
|
async answerCallbackQuery(callbackQueryId, text) {
|
|
3335
3398
|
await fetch(this.apiUrl("answerCallbackQuery"), {
|
|
3336
3399
|
method: "POST",
|
|
@@ -3499,6 +3562,163 @@ ${summary}`;
|
|
|
3499
3562
|
}
|
|
3500
3563
|
};
|
|
3501
3564
|
|
|
3565
|
+
// src/server/freeMode.ts
|
|
3566
|
+
var ENCRYPTED_KEYS = [
|
|
3567
|
+
"FhkYWwEZE0MYBhAGUEADDBYFBEoDBxIHVUpUVRIMVUYDAkEHVRYNAxABUUAEAUMDV0pUDEQAU0ZTDEQCVERQVkoBVhAEBBBXAQ==",
|
|
3568
|
+
"FhkYWwEZE0MYVkIGUkNUUkpVXUsBBUUAVEYHUEIMBhQCVxZWBBcHVkoNUENRAxAMA0MHARBXBkVUAUVQXBAFAUVXVxFWBUtWBw==",
|
|
3569
|
+
"FhkYWwEZE0MYVhFWAUJUUBEMURMHAUoEAUcABRAEURRXARBRU0ZUBBFVB0YAAUNVVUYBDBBSABRUAhdVXUUBUhANV0IMBBABBA==",
|
|
3570
|
+
"FhkYWwEZE0MYUBIDABMBVkMHURcGDRVSXRMFBUUCBBQBVhUBUBEGDBAAVkpTVUoGUBYMBhJXB0ANABUEARBQB0RRXUBRBUNQBw==",
|
|
3571
|
+
"FhkYWwEZE0MYVhcFBhMFARJXVBMADRdWVxYHBkQNA0cBBEsGVEBRAkYCXEFXURBXABZQDEZSXBQHAkJSAUABVxIMA0NWAEcMUA==",
|
|
3572
|
+
"FhkYWwEZE0MYAEQAXEZQURUGARFRBkRWVENWDUYFBkQHBEJWU0dQUkdWBhZXARYMAERXURcBUUQNDUAGAEoEB0ABV0NTUkQDBw==",
|
|
3573
|
+
"FhkYWwEZE0MYABdRURBXVkYDURZWUUIAUEcMBEcMUUpXVxEGVhEMBktVXBBWAEFQBBBRVhECUEQEBkFQUUpRVRUMV0dRA0QGUw==",
|
|
3574
|
+
"FhkYWwEZE0MYVUMCUUIHAUFRVksFVhYMARRRBBIAVBMBDEFVAxMAAUpRXUsEBkMHVhAHBUdSVxECABJSVRdRBkMEURANAEdXVA==",
|
|
3575
|
+
"FhkYWwEZE0MYUkEFVEVUBEoMVkINDUFQUENQAkBSAEVQVhcEAEsDBxVWUkBWAkRSA0ANV0FVBkYMVxcBXUQEUEQCARYDDEpWXA==",
|
|
3576
|
+
"FhkYWwEZE0MYDBcCXBANBRdVU0YEAEsMAUoNUkoMUBYDABcHVEBQBkRVUxdWBUUAAURUVxUGB0oDVxIHABRUAhJRAEUDUkECXQ==",
|
|
3577
|
+
"FhkYWwEZE0MYVhUHVBEBURFQA0EBVRcNUUZXAhVXVkpQAEUHBhNTDUQMXRAGA0JQA0BRBRUHVRQMURVWXUoBVxcEBEYEAEACUQ==",
|
|
3578
|
+
"FhkYWwEZE0MYA0UCB0ZTABUNBhRTAUYAUENQUEANBEMCARdQBkRRBRYDUhdWVhACXBcGBhIDVBFRBRJQUREGDRAAUhQHUhUBAA==",
|
|
3579
|
+
"FhkYWwEZE0MYAUsMARACBBYGVxQHARVQVxRRBRcNUkAFUUQCXBEAUkcBXEMBBEYCXRENBUsBVRYABUJXU0FUAEYBUUpWABEGUw==",
|
|
3580
|
+
"FhkYWwEZE0MYAEdSUBcNAUoFUERUAkcFAEQAB0IBUxcFDUIMBEpQVktWUxdUB0MBXUEBBhIMXRQEUBFQXEMFAEBQXUEMVkoBUQ==",
|
|
3581
|
+
"FhkYWwEZE0MYDBYNUUVUA0ECUREMVhUEBkoCVxJSXEtRUENQVxAMBBcMAxACVkVVBEEDUEYDAURWA0oDXUYAAEEEVxQABUANVg==",
|
|
3582
|
+
"FhkYWwEZE0MYVhcHBhcFV0EBUEdWVxdSU0sMABFSUEIHA0EAU0dWBkcFXEZRBENXAUEDV0AFUkEABBAEXBdXAhZRBEAAUUBSVg==",
|
|
3583
|
+
"FhkYWwEZE0MYV0MHAxYBDUsHB0oFVRJWAUoABEQGAUEHDRdRUBQHBREFUkpQVUYHVkVTDBcDXUYHBkJXUhENVUIAVUtTDRcMVA==",
|
|
3584
|
+
"FhkYWwEZE0MYBxVXBEsAUkYBA0EEAUIGBkRQA0MNABZRVkcHA0JTUEdWUkNRBBUEXUFUB0oFB0QGDBdWUUsEV0NXBBQBVRUEVg==",
|
|
3585
|
+
"FhkYWwEZE0MYVxcCVBYHAEsNVBEADEENUkMAUhFWXBNUVxdWBxNWURYAVEEAUUdSURAHDUsAUkEABBJSVRZQV0YNVRBRDUVSBw==",
|
|
3586
|
+
"FhkYWwEZE0MYAEQEV0YGVxcMVkRQUEsGUEBRUEADAEYEV0NRBBRWBUpXV0oMA0NRXBBRAkAMXUZWURBSXEZRB0EEVBQNVxYBXQ==",
|
|
3587
|
+
"FhkYWwEZE0MYA0IBUhADUERXB0MNB0MHVUtUDRUNBEpXVkEGUBMABkZVUENUAkBVXRAEDEAHBkJWABAEURNWDEcEABQCVUdVVA==",
|
|
3588
|
+
"FhkYWwEZE0MYUhcEBBYCAUFSXUAEAEEBV0sDDRAFV0YDV0NVBENXB0QNVxdUAkYMXUQGA0tRV0tWVUoDAxcGUUVVVUQHDBEDBA==",
|
|
3589
|
+
"FhkYWwEZE0MYA0QBBEIAB0INXUtTBxYFVBFXABJSBkYEAxIAVEAGVkZSB0tQUEoHBkcGBBUHVENWAUNRUEYCAhJSXRcNUEQGUA==",
|
|
3590
|
+
"FhkYWwEZE0MYUBJQUEIFUkBXARBUBUIDAxBQVhJVVkUMVhEDAEYNVxEGBhRUVkJWURYDAUAAAUUMARVRBhYAUkAEUkUEAhYCVg==",
|
|
3591
|
+
"FhkYWwEZE0MYVUYGVBcEDEAFVhACVkFWXBFTAxAMUUpQURENARYBVhABAEINAEQCAUECDEsCBEUBVxBXBxRUVxdQBBRXVkcCUA==",
|
|
3592
|
+
"FhkYWwEZE0MYV0YMVxBTVUNQBERRURVSUxQGUUVWB0MGVUMHV0cHUkMEAEMDDUMCVEcGVkNVB0oDURdVAUFQBkIAURYDBhAHAA==",
|
|
3593
|
+
"FhkYWwEZE0MYUhYCXEsNVUAEURFXBkcHABFQBxcFUENWVkpVAxZWAhEBAxMBBkRRVUtQDEZWXEoBBxUNVkYBBhJQUBBQUUoDBw==",
|
|
3594
|
+
"FhkYWwEZE0MYB0YGXUIGDRIHVRZQVUJSV0UNB0oNAxQADRUMVUcEBhdQV0AHDUZXAEtQVkVQUhBRBUBSUEQCVkRSBEUDUkQEVQ==",
|
|
3595
|
+
"FhkYWwEZE0MYB0MGAUEADERVV0RXDUJSUUMAUEdRAUMCBxZSBktQDUMEBkIBBkIDAEMNURdRXUoFB0RWVEZRDUFXAEJTVRVWVg==",
|
|
3596
|
+
"FhkYWwEZE0MYAkQDAxcFBEpXVEIEDUJSB0tXBhVXUkIDAEEMBBBXDUdRVRcNBURVAxZXUUENARYNBkMAUBBTDUsGVUFWDEcAVQ==",
|
|
3597
|
+
"FhkYWwEZE0MYDRFQVUsCBRIMXBEFBEYEBEMBAUAMVkoCDUoABEcNV0YMU0pWABJXURcAAEIEUBcGVxcGUhZWBUIAVUQCUkVVAA==",
|
|
3598
|
+
"FhkYWwEZE0MYUhcDVURUDBBSVkVWAEYCBkoMUEVVU0cEAxcFVhcDVUEBAEpXUhIAXEUNBUQBAxYGUhFXVUUHBBUAVkpRURAAVQ==",
|
|
3599
|
+
"FhkYWwEZE0MYUEtVV0BQV0tXB0dXVkNRVRRQBUADABFTURYDVBdXUEFSXEpXB0dQVBQEA0oAVUpTBEYEVBMNDEMDU0BUBUINUg==",
|
|
3600
|
+
"FhkYWwEZE0MYUEpQBxZTBkFXXEZWAkEEBxEHB0RXVktQUEMDARRRABEFAUIABEAMARRRDUACBBAMUEMMUxcEUUEEAEoAURBQBg==",
|
|
3601
|
+
"FhkYWwEZE0MYUEINARRQAhcCUEJRUBIFBEIHBkJQB0tWVhINXRBUUBdVBkcMBUZVUxNTAUsMU0cFAEtSXUJXDRJSBkVUAUoBVA==",
|
|
3602
|
+
"FhkYWwEZE0MYUEBWAUtXBxEHUhNTBRZVB0UEB0MDA0sCBEAABkNUAUQCBxYAAEVQUEYDVkoDVxAFVUFVVUcMAUECBkoGUUsCUA==",
|
|
3603
|
+
"FhkYWwEZE0MYBBUBUEFTBUIDAxAGBUcFARBWBRJXUUJTAkUGURQBUUUEB0EFBBBVVURQBEEAUBMAVhINVUEBVUcMA0sNVUNQVg==",
|
|
3604
|
+
"FhkYWwEZE0MYDUMDA0MNA0oAV0BQUEEFBEUBAkpQXBAMBUsCVRZXVkIAXBMEAktXBhYABkcAUhMAUhYBA0BTAURVURMBA0ACXA==",
|
|
3605
|
+
"FhkYWwEZE0MYUhdXUUMDAEQNBhZTAEdWXUYHBxEHXUQCDBYCBkEBBEIDAEBQBkEAUkUBBREMUEUNAEUMBENUBhZXVkVQV0NWBw==",
|
|
3606
|
+
"FhkYWwEZE0MYUBdVU0VXVkpQUkEEBkFSVhZRDEQMXBdQA0QDXUIHUEtWBEABAERXBEoMAxEDUxYMDUVRXUJTUBcFBhQCVkcAVQ==",
|
|
3607
|
+
"FhkYWwEZE0MYDRcBUBYCUEpRABQNVRcHBkQABkZXUkBWURFVU0sMBxINURQMAREHUUcHAUYDB0QBAUNVVUAAARUGUEoAABYGXA==",
|
|
3608
|
+
"FhkYWwEZE0MYAhUCUktQV0oEBxcCVUoCB0pTAUJQXUJTARYAXUsNDRUDUkVQARIHUUJUBEMEVxMFBhEAUUUCBRIAXBMBVUAHAA==",
|
|
3609
|
+
"FhkYWwEZE0MYARcCAUMDVxFQBEZXUEcCAEYDVksNVUpQB0MEB0EEAhVWXRcEUUBQXEoGA0BSAEVWBhdXVUACUUZSUEZXBUZRVg==",
|
|
3610
|
+
"FhkYWwEZE0MYA0oBUhEHABYCBkcMUUcGXRdUDRZXVBZTARUHVkQGV0UAAUoDBxJRVRQBA0oFAUEGBERSVhMGBEBWBEpRAUMGVg==",
|
|
3611
|
+
"FhkYWwEZE0MYVhANVBFXDEoAXEoMBhYMUxMNUEECVEoMAkQFVxANVRcFABdRDRVWXUACBBYHVURUUBACXUNUV0IMAUcCAUIHBw==",
|
|
3612
|
+
"FhkYWwEZE0MYUEUCB0UNDBEFVhQGBhJSBkYHBEMNBhAGUkAFA0AMBUAGUEYDAUZQVUdWUhcHUEcAUhEFB0FQV0VQAUtXBEcDBw==",
|
|
3613
|
+
"FhkYWwEZE0MYAUNSURNTBRANUkRWVxYHXEYMAUYBB0cCBksCAEUHUkVSVUdRURIEBxADBhECVxNRUEcFUxQMUEMMA0MFBEENBA==",
|
|
3614
|
+
"FhkYWwEZE0MYBxBWVkZQAkENVhYNBBUDXBADAUANUkBRVkICBEtRVxEEAEFUDUIDUkNXAxEDAUcHARIAVEJTA0oNVkANB0EGXA==",
|
|
3615
|
+
"FhkYWwEZE0MYV0IGAREGUhZVUEFXVkJVVUECDBcFARcNUhZQXBEFAkMBU0sDUEIFBhcCV0cCXUBTVRADV0YEA0ZQUxACUUsEXA==",
|
|
3616
|
+
"FhkYWwEZE0MYVUoNVUNQURVQUREDAxJSB0AAAkMCABQDAUMGVBYABBJWBxADBENRVEsAVxcAAEdTARUDBBEFUhZSUEQDDRcAXA==",
|
|
3617
|
+
"FhkYWwEZE0MYBhdRVUQBVhcGBhENV0QEAEIGVxcBUxQNUUcAVxZWBEEEVUBTARYGAUFUAUUHBEQEDUsDVEJXDEQNU0sCV0YMAA==",
|
|
3618
|
+
"FhkYWwEZE0MYVktRAENWAkEBXUsGUUEDUkMHB0FXB0cCAhEHARZUBxJWB0IDBERRUkUAAxYDUkYBUkYDV0QDVUcHVxAGA0INVA==",
|
|
3619
|
+
"FhkYWwEZE0MYBkIAVBABVUINV0NTVxYGAUYFVUMBUxYMURAGBksAVUJVBkoHUUQMA0cMAUdQVkUGBUpSAEZTVRANUBYEUEQBVA==",
|
|
3620
|
+
"FhkYWwEZE0MYDEMDA0oCVURRUBZWUkANUEQBAkBSXBBRB0BSVBYGVkAFVRAGDEYDVkMEDBBSBkQHV0JRA0JUBRcFXURTDRZRUw==",
|
|
3621
|
+
"FhkYWwEZE0MYUBJSVEUNUhcGBkYGAhYDUEcAUEsEBxdUUBZSXEcGDEINXEoDBxcFUkdWBEBRVxYNDUYAUBMBVkcCUBcHUUsAXA==",
|
|
3622
|
+
"FhkYWwEZE0MYA0QNUEtWAUMEAEoBUEoAAREDVRYHVkoEV0ZQBEEEUkEAAUIEAUcCVhEHUBUDB0FRVktVVEFXARIHA0NWBUpXBg==",
|
|
3623
|
+
"FhkYWwEZE0MYV0oCAxFXV0YMUxFQAUAAUEVWA0cEB0pUUBAFXUIHDRdQAEQAUkMGU0AEVxEDBBEBAhBRV0QEAxVWU0NQBxECBw==",
|
|
3624
|
+
"FhkYWwEZE0MYUkoCBBMEUkYDBhYFB0IFVkQMVUpSBksMUUcFUxEEDRZVVkUADEoCVhcHUkEHUxACUUJXBBdTVUQDAEFRBxUGAw==",
|
|
3625
|
+
"FhkYWwEZE0MYV0BXBEUCURUNXUYABUpQURYBBUYFVENXBhYCXRBWDUsHA0NRB0oGUREHDRYGUxMBAksEUkINVkNVBEIBAxdWUA==",
|
|
3626
|
+
"FhkYWwEZE0MYBEoCA0MNDEUAXUNUAxYHXBRRURACUEFQBxYDB0dUBksDA0QFVksMAxQFAEZRAxNTA0cMVUENVxEEAUFRBUAHBA==",
|
|
3627
|
+
"FhkYWwEZE0MYB0ENVkAABxEFXEZQAUYHBhMFBBJQBkMCUUZRBERTAkBRBhADVxYEXEADB0RSUUtRUREBXRdXBkAGBEUNBEQCUg==",
|
|
3628
|
+
"FhkYWwEZE0MYVhFVXBAFDBYFBkFTAhIGB0ZRBEJVXURTBBFWBxNUVkBXBEMMBkIHURcDAksAVEMEV0dSUhdXBBJWUkJWAxBRVg==",
|
|
3629
|
+
"FhkYWwEZE0MYBRFRXUoBBUcGBhZUAUBVABYEVkICVkNXDUcMABYFVxdXU0sEBkcFXEYBURUFVUYFABJSA0dTABdRVBRQVRENVg==",
|
|
3630
|
+
"FhkYWwEZE0MYV0VQVhEHVkVVAEFQAhcHBEMMUUANVxNUBUJWVRcEVUoEBBcDUkcNBkoCUUVVVBcDVRZQBBBUVRYNXBZWBUMAAQ==",
|
|
3631
|
+
"FhkYWwEZE0MYAhIHARYBVxIABhYBVxVWUkVXV0ICXUUADBZQAUYBBEUBUEsFBRcFARcGUEtVXEoGABYAUkEGDEBRVUMBB0IFXQ==",
|
|
3632
|
+
"FhkYWwEZE0MYBBUCXEEFBEJVVxZQBEICUxFRBUUNBksHBhFXUUANVhUCV0EMB0QDVURWDBFSVkYDAxYAABdXBhIEUEQMBEUCUg==",
|
|
3633
|
+
"FhkYWwEZE0MYDUsDBEoNAEECURBTAUJXUEpWVUdSBEAMDRBVUkYAUUoDAxFTDEpVVxEHAUYNVUMGVkYAA0cBBRJWBBAHUUIMVw==",
|
|
3634
|
+
"FhkYWwEZE0MYUUUFXUBTUEYHUkoHBBIFBEpRV0NWVRcBAktWBkADBxAMVUZUBhJSBEAEB0MDVkpTABUMUUVUUEABUkJUVkIHAA=="
|
|
3635
|
+
];
|
|
3636
|
+
var DECRYPT_KEY = "er54s4";
|
|
3637
|
+
function xorDecrypt(b64, secret) {
|
|
3638
|
+
const buf = Buffer.from(b64, "base64");
|
|
3639
|
+
const keyBuf = Buffer.from(secret, "utf8");
|
|
3640
|
+
const out = Buffer.alloc(buf.length);
|
|
3641
|
+
for (let i = 0; i < buf.length; i++) {
|
|
3642
|
+
out[i] = buf[i] ^ keyBuf[i % keyBuf.length];
|
|
3643
|
+
}
|
|
3644
|
+
return out.toString("utf8");
|
|
3645
|
+
}
|
|
3646
|
+
function getRandomFreeKey() {
|
|
3647
|
+
if (ENCRYPTED_KEYS.length === 0) return null;
|
|
3648
|
+
const idx = Math.floor(Math.random() * ENCRYPTED_KEYS.length);
|
|
3649
|
+
return xorDecrypt(ENCRYPTED_KEYS[idx], DECRYPT_KEY);
|
|
3650
|
+
}
|
|
3651
|
+
function getFreeKeyCount() {
|
|
3652
|
+
return ENCRYPTED_KEYS.length;
|
|
3653
|
+
}
|
|
3654
|
+
var FREE_MODE_PROVIDER_ID = "openrouter-free";
|
|
3655
|
+
var FREE_MODE_BASE_URL = "https://openrouter.ai/api/v1";
|
|
3656
|
+
var FALLBACK_FREE_MODELS = [
|
|
3657
|
+
"openrouter/free",
|
|
3658
|
+
"google/gemma-4-26b-a4b-it:free",
|
|
3659
|
+
"google/gemma-3-27b-it:free",
|
|
3660
|
+
"meta-llama/llama-3.3-70b-instruct:free",
|
|
3661
|
+
"qwen/qwen3-coder:free"
|
|
3662
|
+
];
|
|
3663
|
+
var cachedFreeModels = null;
|
|
3664
|
+
var cacheTimestamp = 0;
|
|
3665
|
+
var CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
3666
|
+
async function fetchFreeModelsFromOpenRouter() {
|
|
3667
|
+
try {
|
|
3668
|
+
const resp = await fetch("https://openrouter.ai/api/v1/models");
|
|
3669
|
+
if (!resp.ok) return cachedFreeModels ?? FALLBACK_FREE_MODELS;
|
|
3670
|
+
const json = await resp.json();
|
|
3671
|
+
const ids = json.data.filter((m) => m.id.endsWith(":free") || m.id === "openrouter/free").map((m) => m.id);
|
|
3672
|
+
if (ids.length === 0) return cachedFreeModels ?? FALLBACK_FREE_MODELS;
|
|
3673
|
+
const sorted = ["openrouter/free", ...ids.filter((id) => id !== "openrouter/free")];
|
|
3674
|
+
cachedFreeModels = sorted;
|
|
3675
|
+
cacheTimestamp = Date.now();
|
|
3676
|
+
return sorted;
|
|
3677
|
+
} catch {
|
|
3678
|
+
return cachedFreeModels ?? FALLBACK_FREE_MODELS;
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
async function getFreeModels() {
|
|
3682
|
+
if (cachedFreeModels && Date.now() - cacheTimestamp < CACHE_TTL_MS) {
|
|
3683
|
+
return cachedFreeModels;
|
|
3684
|
+
}
|
|
3685
|
+
return fetchFreeModelsFromOpenRouter();
|
|
3686
|
+
}
|
|
3687
|
+
var FREE_MODE_DEFAULT_MODEL = "openrouter/free";
|
|
3688
|
+
var FREE_MODE_STATE_FILE = "webui-free-mode.json";
|
|
3689
|
+
var CUSTOM_PROVIDER_ID = "custom-endpoint";
|
|
3690
|
+
function getFreeModeConfigArgs(state) {
|
|
3691
|
+
if (!state.enabled || !state.apiKey) return [];
|
|
3692
|
+
if (state.provider === "custom" && state.customBaseUrl) {
|
|
3693
|
+
return [
|
|
3694
|
+
"-c",
|
|
3695
|
+
`model_provider="${CUSTOM_PROVIDER_ID}"`,
|
|
3696
|
+
"-c",
|
|
3697
|
+
`model_providers.${CUSTOM_PROVIDER_ID}.name="Custom Endpoint"`,
|
|
3698
|
+
"-c",
|
|
3699
|
+
`model_providers.${CUSTOM_PROVIDER_ID}.base_url="${state.customBaseUrl}"`,
|
|
3700
|
+
"-c",
|
|
3701
|
+
`model_providers.${CUSTOM_PROVIDER_ID}.wire_api="responses"`,
|
|
3702
|
+
"-c",
|
|
3703
|
+
`model_providers.${CUSTOM_PROVIDER_ID}.experimental_bearer_token="${state.apiKey}"`
|
|
3704
|
+
];
|
|
3705
|
+
}
|
|
3706
|
+
return [
|
|
3707
|
+
"-c",
|
|
3708
|
+
`model="${state.model}"`,
|
|
3709
|
+
"-c",
|
|
3710
|
+
`model_provider="${FREE_MODE_PROVIDER_ID}"`,
|
|
3711
|
+
"-c",
|
|
3712
|
+
`model_providers.${FREE_MODE_PROVIDER_ID}.name="OpenRouter Free"`,
|
|
3713
|
+
"-c",
|
|
3714
|
+
`model_providers.${FREE_MODE_PROVIDER_ID}.base_url="${FREE_MODE_BASE_URL}"`,
|
|
3715
|
+
"-c",
|
|
3716
|
+
`model_providers.${FREE_MODE_PROVIDER_ID}.wire_api="responses"`,
|
|
3717
|
+
"-c",
|
|
3718
|
+
`model_providers.${FREE_MODE_PROVIDER_ID}.experimental_bearer_token="${state.apiKey}"`
|
|
3719
|
+
];
|
|
3720
|
+
}
|
|
3721
|
+
|
|
3502
3722
|
// src/utils/commandInvocation.ts
|
|
3503
3723
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
3504
3724
|
import { basename as basename2, extname } from "path";
|
|
@@ -4979,11 +5199,24 @@ async function writeWorkspaceRootsState(nextState) {
|
|
|
4979
5199
|
}
|
|
4980
5200
|
function normalizeTelegramBridgeConfig(value) {
|
|
4981
5201
|
const record = asRecord5(value);
|
|
4982
|
-
if (!record) return { botToken: "", chatIds: [] };
|
|
5202
|
+
if (!record) return { botToken: "", chatIds: [], allowedUserIds: [] };
|
|
4983
5203
|
const botToken = typeof record.botToken === "string" ? record.botToken.trim() : "";
|
|
4984
5204
|
const rawChatIds = Array.isArray(record.chatIds) ? record.chatIds : [];
|
|
4985
5205
|
const chatIds = Array.from(new Set(rawChatIds.filter((value2) => typeof value2 === "number" && Number.isFinite(value2)).map((value2) => Math.trunc(value2)))).slice(0, 50);
|
|
4986
|
-
|
|
5206
|
+
const rawAllowedUserIds = Array.isArray(record.allowedUserIds) ? record.allowedUserIds : [];
|
|
5207
|
+
const allowAllUsers = rawAllowedUserIds.some((value2) => typeof value2 === "string" && value2.trim() === "*");
|
|
5208
|
+
const normalizedAllowedUserIds = Array.from(new Set(rawAllowedUserIds.map((value2) => {
|
|
5209
|
+
if (typeof value2 === "number" && Number.isFinite(value2)) return Math.trunc(value2);
|
|
5210
|
+
if (typeof value2 === "string") {
|
|
5211
|
+
const normalized = value2.trim().replace(/^(telegram|tg):/i, "").trim();
|
|
5212
|
+
if (/^-?\d+$/.test(normalized)) {
|
|
5213
|
+
return Number.parseInt(normalized, 10);
|
|
5214
|
+
}
|
|
5215
|
+
}
|
|
5216
|
+
return Number.NaN;
|
|
5217
|
+
}).filter((value2) => Number.isFinite(value2)))).slice(0, 100);
|
|
5218
|
+
const allowedUserIds = allowAllUsers ? ["*", ...normalizedAllowedUserIds] : normalizedAllowedUserIds;
|
|
5219
|
+
return { botToken, chatIds, allowedUserIds };
|
|
4987
5220
|
}
|
|
4988
5221
|
async function readTelegramBridgeConfig() {
|
|
4989
5222
|
const telegramConfigPath = getTelegramBridgeConfigPath();
|
|
@@ -4992,7 +5225,7 @@ async function readTelegramBridgeConfig() {
|
|
|
4992
5225
|
const payload = asRecord5(JSON.parse(raw)) ?? {};
|
|
4993
5226
|
return normalizeTelegramBridgeConfig(payload);
|
|
4994
5227
|
} catch {
|
|
4995
|
-
return { botToken: "", chatIds: [] };
|
|
5228
|
+
return { botToken: "", chatIds: [], allowedUserIds: [] };
|
|
4996
5229
|
}
|
|
4997
5230
|
}
|
|
4998
5231
|
async function writeTelegramBridgeConfig(nextState) {
|
|
@@ -5000,7 +5233,8 @@ async function writeTelegramBridgeConfig(nextState) {
|
|
|
5000
5233
|
const telegramConfigPath = getTelegramBridgeConfigPath();
|
|
5001
5234
|
await writeFile4(telegramConfigPath, JSON.stringify({
|
|
5002
5235
|
botToken: normalized.botToken,
|
|
5003
|
-
chatIds: normalized.chatIds
|
|
5236
|
+
chatIds: normalized.chatIds,
|
|
5237
|
+
allowedUserIds: normalized.allowedUserIds
|
|
5004
5238
|
}), "utf8");
|
|
5005
5239
|
}
|
|
5006
5240
|
var telegramBridgeConfigMutation = Promise.resolve();
|
|
@@ -5206,10 +5440,27 @@ var AppServerProcess = class {
|
|
|
5206
5440
|
}
|
|
5207
5441
|
return codexCommand;
|
|
5208
5442
|
}
|
|
5443
|
+
buildAppServerArgs() {
|
|
5444
|
+
const args = [
|
|
5445
|
+
"app-server",
|
|
5446
|
+
"-c",
|
|
5447
|
+
'approval_policy="never"',
|
|
5448
|
+
"-c",
|
|
5449
|
+
'sandbox_mode="danger-full-access"'
|
|
5450
|
+
];
|
|
5451
|
+
const statePath = join5(getCodexHomeDir3(), FREE_MODE_STATE_FILE);
|
|
5452
|
+
try {
|
|
5453
|
+
const raw = readFileSync(statePath, "utf8");
|
|
5454
|
+
const state = JSON.parse(raw);
|
|
5455
|
+
args.push(...getFreeModeConfigArgs(state));
|
|
5456
|
+
} catch {
|
|
5457
|
+
}
|
|
5458
|
+
return args;
|
|
5459
|
+
}
|
|
5209
5460
|
start() {
|
|
5210
5461
|
if (this.process) return;
|
|
5211
5462
|
this.stopping = false;
|
|
5212
|
-
const invocation = getSpawnInvocation(this.getCodexCommand(), this.
|
|
5463
|
+
const invocation = getSpawnInvocation(this.getCodexCommand(), this.buildAppServerArgs());
|
|
5213
5464
|
const proc = spawn4(invocation.command, invocation.args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
5214
5465
|
this.process = proc;
|
|
5215
5466
|
proc.stdout.setEncoding("utf8");
|
|
@@ -5758,6 +6009,7 @@ function createCodexBridgeMiddleware() {
|
|
|
5758
6009
|
void readTelegramBridgeConfig().then((config) => {
|
|
5759
6010
|
if (!config.botToken) return;
|
|
5760
6011
|
telegramBridge.configureToken(config.botToken);
|
|
6012
|
+
telegramBridge.configureAllowedUserIds(config.allowedUserIds);
|
|
5761
6013
|
telegramBridge.start();
|
|
5762
6014
|
}).catch(() => {
|
|
5763
6015
|
});
|
|
@@ -5768,6 +6020,135 @@ function createCodexBridgeMiddleware() {
|
|
|
5768
6020
|
return;
|
|
5769
6021
|
}
|
|
5770
6022
|
const url = new URL(req.url, "http://localhost");
|
|
6023
|
+
if (url.pathname.startsWith("/codex-api/free-mode")) {
|
|
6024
|
+
let readFreeModeState2 = function() {
|
|
6025
|
+
try {
|
|
6026
|
+
return JSON.parse(readFileSync(statePath, "utf8"));
|
|
6027
|
+
} catch {
|
|
6028
|
+
return { enabled: false, apiKey: null, model: FREE_MODE_DEFAULT_MODEL };
|
|
6029
|
+
}
|
|
6030
|
+
};
|
|
6031
|
+
var readFreeModeState = readFreeModeState2;
|
|
6032
|
+
const statePath = join5(getCodexHomeDir3(), FREE_MODE_STATE_FILE);
|
|
6033
|
+
if (req.method === "POST" && url.pathname === "/codex-api/free-mode") {
|
|
6034
|
+
try {
|
|
6035
|
+
const body = await readJsonBody(req);
|
|
6036
|
+
const enable = Boolean(body?.enable);
|
|
6037
|
+
if (enable) {
|
|
6038
|
+
const apiKey = getRandomFreeKey();
|
|
6039
|
+
if (!apiKey) {
|
|
6040
|
+
setJson4(res, 500, { error: "No free keys available" });
|
|
6041
|
+
return;
|
|
6042
|
+
}
|
|
6043
|
+
const state = { enabled: true, apiKey, model: FREE_MODE_DEFAULT_MODEL, provider: "openrouter" };
|
|
6044
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6045
|
+
appServer.dispose();
|
|
6046
|
+
const freeModels = await getFreeModels();
|
|
6047
|
+
setJson4(res, 200, {
|
|
6048
|
+
ok: true,
|
|
6049
|
+
enabled: true,
|
|
6050
|
+
model: FREE_MODE_DEFAULT_MODEL,
|
|
6051
|
+
keyCount: getFreeKeyCount(),
|
|
6052
|
+
models: freeModels
|
|
6053
|
+
});
|
|
6054
|
+
} else {
|
|
6055
|
+
const state = { enabled: false, apiKey: null, model: FREE_MODE_DEFAULT_MODEL };
|
|
6056
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6057
|
+
appServer.dispose();
|
|
6058
|
+
setJson4(res, 200, { ok: true, enabled: false });
|
|
6059
|
+
}
|
|
6060
|
+
} catch (error) {
|
|
6061
|
+
setJson4(res, 500, { error: getErrorMessage5(error, "Failed to toggle free mode") });
|
|
6062
|
+
}
|
|
6063
|
+
return;
|
|
6064
|
+
}
|
|
6065
|
+
if (req.method === "GET" && url.pathname === "/codex-api/free-mode/status") {
|
|
6066
|
+
try {
|
|
6067
|
+
const state = readFreeModeState2();
|
|
6068
|
+
const freeModels = await getFreeModels();
|
|
6069
|
+
const maskedKey = state.apiKey && state.customKey ? state.apiKey.substring(0, 12) + "..." + state.apiKey.substring(state.apiKey.length - 4) : null;
|
|
6070
|
+
setJson4(res, 200, {
|
|
6071
|
+
enabled: state.enabled,
|
|
6072
|
+
keyCount: getFreeKeyCount(),
|
|
6073
|
+
models: freeModels,
|
|
6074
|
+
currentModel: state.enabled ? state.model : null,
|
|
6075
|
+
customKey: Boolean(state.customKey),
|
|
6076
|
+
maskedKey,
|
|
6077
|
+
provider: state.provider ?? "openrouter",
|
|
6078
|
+
customBaseUrl: state.customBaseUrl ?? null
|
|
6079
|
+
});
|
|
6080
|
+
} catch (error) {
|
|
6081
|
+
setJson4(res, 500, { error: getErrorMessage5(error, "Failed to read free mode status") });
|
|
6082
|
+
}
|
|
6083
|
+
return;
|
|
6084
|
+
}
|
|
6085
|
+
if (req.method === "POST" && url.pathname === "/codex-api/free-mode/rotate-key") {
|
|
6086
|
+
try {
|
|
6087
|
+
const apiKey = getRandomFreeKey();
|
|
6088
|
+
if (!apiKey) {
|
|
6089
|
+
setJson4(res, 500, { error: "No free keys available" });
|
|
6090
|
+
return;
|
|
6091
|
+
}
|
|
6092
|
+
const current = readFreeModeState2();
|
|
6093
|
+
const state = { ...current, apiKey, customKey: false };
|
|
6094
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6095
|
+
appServer.dispose();
|
|
6096
|
+
setJson4(res, 200, { ok: true });
|
|
6097
|
+
} catch (error) {
|
|
6098
|
+
setJson4(res, 500, { error: getErrorMessage5(error, "Failed to rotate key") });
|
|
6099
|
+
}
|
|
6100
|
+
return;
|
|
6101
|
+
}
|
|
6102
|
+
if (req.method === "POST" && url.pathname === "/codex-api/free-mode/custom-key") {
|
|
6103
|
+
try {
|
|
6104
|
+
const body = await readJsonBody(req);
|
|
6105
|
+
const key = typeof body?.key === "string" ? body.key.trim() : "";
|
|
6106
|
+
const current = readFreeModeState2();
|
|
6107
|
+
if (key.length > 0) {
|
|
6108
|
+
const state = { ...current, enabled: true, apiKey: key, customKey: true, provider: "openrouter" };
|
|
6109
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6110
|
+
appServer.dispose();
|
|
6111
|
+
setJson4(res, 200, { ok: true, customKey: true });
|
|
6112
|
+
} else {
|
|
6113
|
+
const communityKey = getRandomFreeKey();
|
|
6114
|
+
const state = { ...current, apiKey: communityKey, customKey: false, provider: "openrouter" };
|
|
6115
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6116
|
+
appServer.dispose();
|
|
6117
|
+
setJson4(res, 200, { ok: true, customKey: false });
|
|
6118
|
+
}
|
|
6119
|
+
} catch (error) {
|
|
6120
|
+
setJson4(res, 500, { error: getErrorMessage5(error, "Failed to set custom key") });
|
|
6121
|
+
}
|
|
6122
|
+
return;
|
|
6123
|
+
}
|
|
6124
|
+
if (req.method === "POST" && url.pathname === "/codex-api/free-mode/custom-provider") {
|
|
6125
|
+
try {
|
|
6126
|
+
const body = await readJsonBody(req);
|
|
6127
|
+
const baseUrl = typeof body?.baseUrl === "string" ? body.baseUrl.trim() : "";
|
|
6128
|
+
const apiKey = typeof body?.apiKey === "string" ? body.apiKey.trim() : "";
|
|
6129
|
+
if (!baseUrl) {
|
|
6130
|
+
setJson4(res, 400, { error: "baseUrl is required" });
|
|
6131
|
+
return;
|
|
6132
|
+
}
|
|
6133
|
+
const state = {
|
|
6134
|
+
enabled: true,
|
|
6135
|
+
apiKey: apiKey || "dummy",
|
|
6136
|
+
model: "",
|
|
6137
|
+
customKey: true,
|
|
6138
|
+
provider: "custom",
|
|
6139
|
+
customBaseUrl: baseUrl
|
|
6140
|
+
};
|
|
6141
|
+
await writeFile4(statePath, JSON.stringify(state), "utf8");
|
|
6142
|
+
appServer.dispose();
|
|
6143
|
+
setJson4(res, 200, { ok: true });
|
|
6144
|
+
} catch (error) {
|
|
6145
|
+
setJson4(res, 500, { error: getErrorMessage5(error, "Failed to set custom provider") });
|
|
6146
|
+
}
|
|
6147
|
+
return;
|
|
6148
|
+
}
|
|
6149
|
+
next();
|
|
6150
|
+
return;
|
|
6151
|
+
}
|
|
5771
6152
|
if (!url.pathname.startsWith("/codex-api/")) {
|
|
5772
6153
|
next();
|
|
5773
6154
|
return;
|
|
@@ -6038,6 +6419,34 @@ function createCodexBridgeMiddleware() {
|
|
|
6038
6419
|
return;
|
|
6039
6420
|
}
|
|
6040
6421
|
if (req.method === "GET" && url.pathname === "/codex-api/provider-models") {
|
|
6422
|
+
try {
|
|
6423
|
+
const fmState = JSON.parse(readFileSync(join5(getCodexHomeDir3(), FREE_MODE_STATE_FILE), "utf8"));
|
|
6424
|
+
if (fmState.enabled) {
|
|
6425
|
+
if (fmState.provider === "custom" && fmState.customBaseUrl) {
|
|
6426
|
+
try {
|
|
6427
|
+
const modelsUrl = fmState.customBaseUrl.replace(/\/+$/, "") + "/models";
|
|
6428
|
+
const headers = {};
|
|
6429
|
+
if (fmState.apiKey && fmState.apiKey !== "dummy") {
|
|
6430
|
+
headers["Authorization"] = `Bearer ${fmState.apiKey}`;
|
|
6431
|
+
}
|
|
6432
|
+
const resp = await fetch(modelsUrl, { headers, signal: AbortSignal.timeout(8e3) });
|
|
6433
|
+
if (resp.ok) {
|
|
6434
|
+
const json = await resp.json();
|
|
6435
|
+
const ids = (json.data ?? []).map((m) => m.id).filter(Boolean);
|
|
6436
|
+
setJson4(res, 200, { data: ids, exclusive: true, source: "custom" });
|
|
6437
|
+
return;
|
|
6438
|
+
}
|
|
6439
|
+
} catch {
|
|
6440
|
+
}
|
|
6441
|
+
setJson4(res, 200, { data: [], exclusive: true, source: "custom" });
|
|
6442
|
+
return;
|
|
6443
|
+
}
|
|
6444
|
+
const freeModels = await getFreeModels();
|
|
6445
|
+
setJson4(res, 200, { data: freeModels, exclusive: true });
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
6448
|
+
} catch {
|
|
6449
|
+
}
|
|
6041
6450
|
const data = await readProviderBackedModelIds(appServer);
|
|
6042
6451
|
setJson4(res, 200, data);
|
|
6043
6452
|
return;
|
|
@@ -6495,20 +6904,41 @@ function createCodexBridgeMiddleware() {
|
|
|
6495
6904
|
if (req.method === "POST" && url.pathname === "/codex-api/telegram/configure-bot") {
|
|
6496
6905
|
const payload = asRecord5(await readJsonBody(req));
|
|
6497
6906
|
const botToken = typeof payload?.botToken === "string" ? payload.botToken.trim() : "";
|
|
6907
|
+
const rawAllowedUserIds = Array.isArray(payload?.allowedUserIds) ? payload.allowedUserIds : [];
|
|
6498
6908
|
if (!botToken) {
|
|
6499
6909
|
setJson4(res, 400, { error: "Missing botToken" });
|
|
6500
6910
|
return;
|
|
6501
6911
|
}
|
|
6502
|
-
|
|
6912
|
+
const config = normalizeTelegramBridgeConfig({
|
|
6913
|
+
botToken,
|
|
6914
|
+
allowedUserIds: rawAllowedUserIds
|
|
6915
|
+
});
|
|
6916
|
+
if (config.allowedUserIds.length === 0) {
|
|
6917
|
+
setJson4(res, 400, { error: "At least one allowed Telegram user ID is required" });
|
|
6918
|
+
return;
|
|
6919
|
+
}
|
|
6920
|
+
telegramBridge.configureToken(config.botToken);
|
|
6921
|
+
telegramBridge.configureAllowedUserIds(config.allowedUserIds);
|
|
6503
6922
|
telegramBridge.start();
|
|
6504
6923
|
const existingConfig = await readTelegramBridgeConfig();
|
|
6505
6924
|
await writeTelegramBridgeConfig({
|
|
6506
|
-
botToken,
|
|
6507
|
-
chatIds: existingConfig.chatIds
|
|
6925
|
+
botToken: config.botToken,
|
|
6926
|
+
chatIds: existingConfig.chatIds,
|
|
6927
|
+
allowedUserIds: config.allowedUserIds
|
|
6508
6928
|
});
|
|
6509
6929
|
setJson4(res, 200, { ok: true });
|
|
6510
6930
|
return;
|
|
6511
6931
|
}
|
|
6932
|
+
if (req.method === "GET" && url.pathname === "/codex-api/telegram/config") {
|
|
6933
|
+
const config = await readTelegramBridgeConfig();
|
|
6934
|
+
setJson4(res, 200, {
|
|
6935
|
+
data: {
|
|
6936
|
+
botToken: config.botToken,
|
|
6937
|
+
allowedUserIds: config.allowedUserIds
|
|
6938
|
+
}
|
|
6939
|
+
});
|
|
6940
|
+
return;
|
|
6941
|
+
}
|
|
6512
6942
|
if (req.method === "GET" && url.pathname === "/codex-api/telegram/status") {
|
|
6513
6943
|
setJson4(res, 200, { data: telegramBridge.getStatus() });
|
|
6514
6944
|
return;
|
|
@@ -7776,6 +8206,8 @@ async function startServer(options) {
|
|
|
7776
8206
|
if (options.login && !hasCodexAuth() && codexCommand) {
|
|
7777
8207
|
console.log("\nCodex is not logged in. Starting `codex login`...\n");
|
|
7778
8208
|
runOrFail(codexCommand, ["login"], "Codex login");
|
|
8209
|
+
} else if (options.login && !hasCodexAuth()) {
|
|
8210
|
+
console.log("\nCodex is not logged in. You can log in later via settings or run `codexui login`.\n");
|
|
7779
8211
|
}
|
|
7780
8212
|
const requestedPort = parseInt(options.port, 10);
|
|
7781
8213
|
const password = resolvePassword(options.password);
|