appback-remoteagent 0.23.0 → 0.23.2
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 +1 -1
- package/dist/adapters/codex-adapter.js +6 -0
- package/dist/bot.js +127 -8
- package/dist/index.js +6 -33
- package/dist/services/bridge-service.js +4 -3
- package/package.json +1 -1
- package/scripts/selftest-codex-stream.mjs +6 -0
- package/scripts/selftest-model-fallback.mjs +2 -1
- package/scripts/selftest-telegram-update.mjs +16 -0
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ Current command surface implemented in `src/bot.ts`:
|
|
|
105
105
|
| `/new` | Creates and binds a new session using the saved default mode in a new managed workspace |
|
|
106
106
|
| `/switch <session>` | Rebinds this chat to an existing RemoteAgent session |
|
|
107
107
|
| `/status` | Shows current session, workspace, provider, and sandbox state |
|
|
108
|
-
| `/model [name]` | Lists selectable provider models or changes the current session model |
|
|
108
|
+
| `/model [name]` | Lists selectable provider models or changes the current session model. New Codex sessions default to `gpt-6-astra` with `medium` reasoning. Use `/model gpt-6-astra` for an existing session. |
|
|
109
109
|
| `/sandbox [codex <mode>]` | Lists Codex sandbox choices or changes the current session sandbox |
|
|
110
110
|
| `/option retry <count>` | Sets the automatic continuation turn limit and persists it to `~/.remoteagent/.env` |
|
|
111
111
|
| `/option timeout <seconds>` | Sets the provider execution timeout and persists it to `~/.remoteagent/.env` |
|
|
@@ -67,6 +67,9 @@ export class CodexAdapter {
|
|
|
67
67
|
if (request.model) {
|
|
68
68
|
args.push("-m", request.model);
|
|
69
69
|
}
|
|
70
|
+
if (request.model === "gpt-6-astra") {
|
|
71
|
+
args.push("-c", 'model_reasoning_effort="medium"');
|
|
72
|
+
}
|
|
70
73
|
this.appendSandboxArgs(args, sandboxMode);
|
|
71
74
|
args.push("-o", outputPath, "-C", request.cwd);
|
|
72
75
|
this.appendPromptStdinArg(args);
|
|
@@ -82,6 +85,9 @@ export class CodexAdapter {
|
|
|
82
85
|
if (request.model) {
|
|
83
86
|
args.push("-m", request.model);
|
|
84
87
|
}
|
|
88
|
+
if (request.model === "gpt-6-astra") {
|
|
89
|
+
args.push("-c", 'model_reasoning_effort="medium"');
|
|
90
|
+
}
|
|
85
91
|
this.appendSandboxArgs(args, sandboxMode);
|
|
86
92
|
args.push("-o", outputPath, request.sessionId);
|
|
87
93
|
this.appendPromptStdinArg(args);
|
package/dist/bot.js
CHANGED
|
@@ -1452,6 +1452,10 @@ async function runWithPendingAnimation(botToken, chatId, task) {
|
|
|
1452
1452
|
typingStopped = true;
|
|
1453
1453
|
return;
|
|
1454
1454
|
}
|
|
1455
|
+
if (isTelegramRateLimitError(error)) {
|
|
1456
|
+
console.warn(`[telegram-chat-action] chat=${chatId} paused by Telegram rate limit: ${formatTelegramDeliveryError(error)}`);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1455
1459
|
console.warn(`[telegram-chat-action] chat=${chatId} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1456
1460
|
})
|
|
1457
1461
|
.finally(() => {
|
|
@@ -1467,6 +1471,9 @@ async function runWithPendingAnimation(botToken, chatId, task) {
|
|
|
1467
1471
|
try {
|
|
1468
1472
|
const helpers = {
|
|
1469
1473
|
reportProgress: async (chunks, parseMode, messageOptions) => {
|
|
1474
|
+
if (getTelegramRateLimitDelayMs(botToken) > 0) {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1470
1477
|
const normalized = await normalizeTelegramDelivery(chunks);
|
|
1471
1478
|
const progressChunks = flattenChunks(normalized.chunks, 3900);
|
|
1472
1479
|
if (progressChunks.length === 0 && normalized.documents.length === 0) {
|
|
@@ -1478,12 +1485,12 @@ async function runWithPendingAnimation(botToken, chatId, task) {
|
|
|
1478
1485
|
...(rendered.parseMode ? { parse_mode: rendered.parseMode } : {}),
|
|
1479
1486
|
};
|
|
1480
1487
|
for (const chunk of rendered.chunks) {
|
|
1481
|
-
await sendTelegramMessage(botToken, chatId, chunk, extra).catch((error) => {
|
|
1488
|
+
await sendTelegramMessage(botToken, chatId, chunk, extra, "progress").catch((error) => {
|
|
1482
1489
|
console.warn(`[telegram-progress-delivery] chat=${chatId} dropped progress message: ${formatTelegramDeliveryError(error)}`);
|
|
1483
1490
|
});
|
|
1484
1491
|
}
|
|
1485
1492
|
if (normalized.documents.length > 0) {
|
|
1486
|
-
await sendTelegramDocuments(botToken, chatId, normalized.documents).catch((error) => {
|
|
1493
|
+
await sendTelegramDocuments(botToken, chatId, normalized.documents, "progress").catch((error) => {
|
|
1487
1494
|
console.warn(`[telegram-progress-delivery] chat=${chatId} dropped progress document(s): ${formatTelegramDeliveryError(error)}`);
|
|
1488
1495
|
});
|
|
1489
1496
|
}
|
|
@@ -3052,9 +3059,29 @@ async function isReadableTelegramDocument(filePath) {
|
|
|
3052
3059
|
return false;
|
|
3053
3060
|
}
|
|
3054
3061
|
}
|
|
3055
|
-
async function sendTelegramDocuments(botToken, chatId, documents) {
|
|
3062
|
+
async function sendTelegramDocuments(botToken, chatId, documents, deliveryClass = "final") {
|
|
3063
|
+
if (deliveryClass === "progress" && getTelegramRateLimitDelayMs(botToken) > 0) {
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3056
3066
|
for (const document of documents) {
|
|
3057
|
-
|
|
3067
|
+
if (deliveryClass === "progress") {
|
|
3068
|
+
await sendTelegramDocument(botToken, chatId, document);
|
|
3069
|
+
continue;
|
|
3070
|
+
}
|
|
3071
|
+
await serializeTelegramMessage(botToken, async () => {
|
|
3072
|
+
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
3073
|
+
await waitForTelegramRateLimit(botToken);
|
|
3074
|
+
try {
|
|
3075
|
+
await sendTelegramDocument(botToken, chatId, document);
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
catch (error) {
|
|
3079
|
+
if (!isTelegramRateLimitError(error) || attempt >= 3) {
|
|
3080
|
+
throw error;
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
});
|
|
3058
3085
|
}
|
|
3059
3086
|
}
|
|
3060
3087
|
async function sendTelegramDocument(botToken, chatId, document) {
|
|
@@ -3081,7 +3108,14 @@ async function sendTelegramDocument(botToken, chatId, document) {
|
|
|
3081
3108
|
}
|
|
3082
3109
|
const payload = JSON.parse(stdout);
|
|
3083
3110
|
if (!payload.ok || !payload.result) {
|
|
3084
|
-
|
|
3111
|
+
const retryAfterSeconds = payload.parameters?.retry_after;
|
|
3112
|
+
const retryAfterMs = typeof retryAfterSeconds === "number" && retryAfterSeconds > 0
|
|
3113
|
+
? Math.ceil(retryAfterSeconds * 1000) + 250
|
|
3114
|
+
: undefined;
|
|
3115
|
+
if (payload.error_code === 429 || retryAfterMs !== undefined) {
|
|
3116
|
+
registerTelegramRateLimit(botToken, retryAfterMs ?? 5_250);
|
|
3117
|
+
}
|
|
3118
|
+
throw new TelegramApiError("sendDocument", payload.description || "Telegram API sendDocument failed.", payload.error_code, retryAfterMs);
|
|
3085
3119
|
}
|
|
3086
3120
|
return payload.result;
|
|
3087
3121
|
}
|
|
@@ -3104,11 +3138,23 @@ async function deleteTelegramMessage(botToken, chatId, messageId) {
|
|
|
3104
3138
|
throw new Error(payload.description || "Telegram API deleteMessage failed.");
|
|
3105
3139
|
}
|
|
3106
3140
|
}
|
|
3107
|
-
async function sendTelegramMessage(botToken, chatId, text, extra) {
|
|
3141
|
+
async function sendTelegramMessage(botToken, chatId, text, extra, deliveryClass = "final") {
|
|
3142
|
+
if (deliveryClass === "progress") {
|
|
3143
|
+
if (getTelegramRateLimitDelayMs(botToken) > 0) {
|
|
3144
|
+
throw new TelegramDeliveryDeferredError("Telegram progress delivery skipped during rate-limit cooldown.");
|
|
3145
|
+
}
|
|
3146
|
+
return sendTelegramMessageNow(botToken, chatId, text, extra, deliveryClass);
|
|
3147
|
+
}
|
|
3148
|
+
return serializeTelegramMessage(botToken, () => sendTelegramMessageNow(botToken, chatId, text, extra, deliveryClass));
|
|
3149
|
+
}
|
|
3150
|
+
async function sendTelegramMessageNow(botToken, chatId, text, extra, deliveryClass) {
|
|
3108
3151
|
const startedAt = Date.now();
|
|
3109
3152
|
try {
|
|
3110
3153
|
let lastError;
|
|
3111
3154
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
3155
|
+
if (deliveryClass === "final") {
|
|
3156
|
+
await waitForTelegramRateLimit(botToken);
|
|
3157
|
+
}
|
|
3112
3158
|
try {
|
|
3113
3159
|
try {
|
|
3114
3160
|
return await callTelegramApi(botToken, "sendMessage", {
|
|
@@ -3132,6 +3178,15 @@ async function sendTelegramMessage(botToken, chatId, text, extra) {
|
|
|
3132
3178
|
}
|
|
3133
3179
|
catch (error) {
|
|
3134
3180
|
lastError = error;
|
|
3181
|
+
if (isTelegramRateLimitError(error)) {
|
|
3182
|
+
if (deliveryClass === "progress" || attempt >= 3) {
|
|
3183
|
+
throw error;
|
|
3184
|
+
}
|
|
3185
|
+
const delayMs = getTelegramRateLimitDelayMs(botToken);
|
|
3186
|
+
console.warn(`[telegram-sendMessage-rate-limit] chat=${chatId} attempt=${attempt}/3 retryAfterMs=${delayMs}`);
|
|
3187
|
+
await waitForTelegramRateLimit(botToken);
|
|
3188
|
+
continue;
|
|
3189
|
+
}
|
|
3135
3190
|
if (attempt >= 3 || !isRetryableTelegramDeliveryError(error)) {
|
|
3136
3191
|
throw error;
|
|
3137
3192
|
}
|
|
@@ -3163,6 +3218,9 @@ function stripTelegramHtml(value) {
|
|
|
3163
3218
|
.replace(/&/g, "&");
|
|
3164
3219
|
}
|
|
3165
3220
|
async function sendTelegramChatAction(botToken, chatId, action) {
|
|
3221
|
+
if (getTelegramRateLimitDelayMs(botToken) > 0) {
|
|
3222
|
+
return;
|
|
3223
|
+
}
|
|
3166
3224
|
await callTelegramApi(botToken, "sendChatAction", {
|
|
3167
3225
|
chat_id: String(chatId),
|
|
3168
3226
|
action,
|
|
@@ -3195,20 +3253,78 @@ async function callTelegramApi(botToken, method, params) {
|
|
|
3195
3253
|
}
|
|
3196
3254
|
const payload = JSON.parse(stdout);
|
|
3197
3255
|
if (!payload.ok) {
|
|
3198
|
-
|
|
3256
|
+
const retryAfterSeconds = payload.parameters?.retry_after;
|
|
3257
|
+
const retryAfterMs = typeof retryAfterSeconds === "number" && retryAfterSeconds > 0
|
|
3258
|
+
? Math.ceil(retryAfterSeconds * 1000) + 250
|
|
3259
|
+
: undefined;
|
|
3260
|
+
if (payload.error_code === 429 || retryAfterMs !== undefined) {
|
|
3261
|
+
registerTelegramRateLimit(botToken, retryAfterMs ?? 5_250);
|
|
3262
|
+
}
|
|
3263
|
+
throw new TelegramApiError(method, payload.description || `Telegram API ${method} failed.`, payload.error_code, retryAfterMs);
|
|
3199
3264
|
}
|
|
3200
3265
|
return payload.result;
|
|
3201
3266
|
}
|
|
3202
3267
|
class TelegramApiError extends Error {
|
|
3203
3268
|
method;
|
|
3204
3269
|
description;
|
|
3205
|
-
|
|
3270
|
+
errorCode;
|
|
3271
|
+
retryAfterMs;
|
|
3272
|
+
constructor(method, description, errorCode, retryAfterMs) {
|
|
3206
3273
|
super(description);
|
|
3207
3274
|
this.method = method;
|
|
3208
3275
|
this.description = description;
|
|
3276
|
+
this.errorCode = errorCode;
|
|
3277
|
+
this.retryAfterMs = retryAfterMs;
|
|
3209
3278
|
this.name = "TelegramApiError";
|
|
3210
3279
|
}
|
|
3211
3280
|
}
|
|
3281
|
+
class TelegramDeliveryDeferredError extends Error {
|
|
3282
|
+
constructor(message) {
|
|
3283
|
+
super(message);
|
|
3284
|
+
this.name = "TelegramDeliveryDeferredError";
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
const telegramRateLimitUntil = new Map();
|
|
3288
|
+
const telegramMessageQueues = new Map();
|
|
3289
|
+
function telegramBotKey(botToken) {
|
|
3290
|
+
return botToken.split(":", 1)[0] || botToken;
|
|
3291
|
+
}
|
|
3292
|
+
function registerTelegramRateLimit(botToken, retryAfterMs) {
|
|
3293
|
+
const key = telegramBotKey(botToken);
|
|
3294
|
+
const until = Date.now() + Math.max(250, retryAfterMs);
|
|
3295
|
+
telegramRateLimitUntil.set(key, Math.max(telegramRateLimitUntil.get(key) ?? 0, until));
|
|
3296
|
+
}
|
|
3297
|
+
function getTelegramRateLimitDelayMs(botToken) {
|
|
3298
|
+
const key = telegramBotKey(botToken);
|
|
3299
|
+
const until = telegramRateLimitUntil.get(key) ?? 0;
|
|
3300
|
+
const delayMs = until - Date.now();
|
|
3301
|
+
if (delayMs <= 0) {
|
|
3302
|
+
telegramRateLimitUntil.delete(key);
|
|
3303
|
+
return 0;
|
|
3304
|
+
}
|
|
3305
|
+
return delayMs;
|
|
3306
|
+
}
|
|
3307
|
+
async function waitForTelegramRateLimit(botToken) {
|
|
3308
|
+
const delayMs = getTelegramRateLimitDelayMs(botToken);
|
|
3309
|
+
if (delayMs > 0) {
|
|
3310
|
+
await sleep(delayMs);
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
async function serializeTelegramMessage(botToken, task) {
|
|
3314
|
+
const key = telegramBotKey(botToken);
|
|
3315
|
+
const previous = telegramMessageQueues.get(key) ?? Promise.resolve();
|
|
3316
|
+
const current = previous.catch(() => undefined).then(task);
|
|
3317
|
+
const tail = current.then(() => undefined, () => undefined);
|
|
3318
|
+
telegramMessageQueues.set(key, tail);
|
|
3319
|
+
try {
|
|
3320
|
+
return await current;
|
|
3321
|
+
}
|
|
3322
|
+
finally {
|
|
3323
|
+
if (telegramMessageQueues.get(key) === tail) {
|
|
3324
|
+
telegramMessageQueues.delete(key);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3212
3328
|
function summarizeCurlTelegramError(error, method) {
|
|
3213
3329
|
if (!(error instanceof Error)) {
|
|
3214
3330
|
return `Telegram API ${method} failed: ${String(error)}`;
|
|
@@ -3229,6 +3345,9 @@ function isRetryableTelegramDeliveryError(error) {
|
|
|
3229
3345
|
const message = formatTelegramDeliveryError(error);
|
|
3230
3346
|
return /timed out|timeout|Bad Gateway|502|503|504|ECONNRESET|connection reset|EAI_AGAIN|ENOTFOUND/i.test(message);
|
|
3231
3347
|
}
|
|
3348
|
+
function isTelegramRateLimitError(error) {
|
|
3349
|
+
return error instanceof TelegramApiError && (error.errorCode === 429 || error.retryAfterMs !== undefined);
|
|
3350
|
+
}
|
|
3232
3351
|
function isTelegramForbiddenError(error) {
|
|
3233
3352
|
if (error instanceof GrammyError) {
|
|
3234
3353
|
return error.error_code === 403 || /^Forbidden:/i.test(error.description);
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,6 @@ import { ProviderRecoveryService } from "./services/provider-recovery-service.js
|
|
|
20
20
|
import { computePolicyPollIntervalMs, computeRecentMessageRanks } from "./services/polling-policy.js";
|
|
21
21
|
import { terminateAllSpawnedExecutions } from "./adapters/windows-shell.js";
|
|
22
22
|
import { buildProviderEnv } from "./adapters/runtime-env.js";
|
|
23
|
-
import { setTelegramCommandMenu } from "./telegram-command-menu.js";
|
|
24
23
|
import { buildBotInfoFromIdentity, buildFallbackBotInfo } from "./telegram-bot-identity.js";
|
|
25
24
|
const execFileAsync = promisify(execFile);
|
|
26
25
|
const TELEGRAM_GET_UPDATES_HTTP_TIMEOUT_SECONDS = 30;
|
|
@@ -72,20 +71,14 @@ async function main() {
|
|
|
72
71
|
}
|
|
73
72
|
const botInfos = await Promise.all(config.telegramBotTokens.map((token, index) => resolveBotInfo(token, index, config.telegramBotUsernames[index])));
|
|
74
73
|
const bots = config.telegramBotTokens.map((token, index) => createBot(token, bridge, botManagement, botInfos[index]));
|
|
75
|
-
if (config.telegramCommandMenuEnabled) {
|
|
76
|
-
|
|
77
|
-
const username = bot.botInfo.username;
|
|
78
|
-
await configureTelegramCommandMenu(bot).catch((error) => {
|
|
79
|
-
console.error(`Failed to configure command menu for @${username}:`, error);
|
|
80
|
-
});
|
|
81
|
-
console.log(`Bot @${username} is ready`);
|
|
82
|
-
}
|
|
74
|
+
if (!config.telegramCommandMenuEnabled) {
|
|
75
|
+
console.log("Telegram command menu registration is disabled.");
|
|
83
76
|
}
|
|
84
77
|
else {
|
|
85
|
-
console.log("Telegram command menu
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
78
|
+
console.log("Telegram command menu startup refresh is skipped; use /option command-menu refresh to apply changes.");
|
|
79
|
+
}
|
|
80
|
+
for (const bot of bots) {
|
|
81
|
+
console.log(`Bot @${bot.botInfo.username} is ready`);
|
|
89
82
|
}
|
|
90
83
|
await botManagement.reportPendingOperationResult().catch((error) => {
|
|
91
84
|
console.error("Failed to report pending bot operation result:", error);
|
|
@@ -140,26 +133,6 @@ function startArtifactCleanupSchedule(memoryService) {
|
|
|
140
133
|
}, config.artifactCleanupIntervalMs);
|
|
141
134
|
interval.unref();
|
|
142
135
|
}
|
|
143
|
-
async function configureTelegramCommandMenu(bot) {
|
|
144
|
-
const token = bot.token;
|
|
145
|
-
if (!token) {
|
|
146
|
-
throw new Error("Telegram bot token is unavailable for command menu registration.");
|
|
147
|
-
}
|
|
148
|
-
let lastError;
|
|
149
|
-
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
150
|
-
try {
|
|
151
|
-
await setTelegramCommandMenu(token);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
catch (error) {
|
|
155
|
-
lastError = error;
|
|
156
|
-
if (attempt < 3) {
|
|
157
|
-
await sleep(1000 * attempt);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
throw lastError;
|
|
162
|
-
}
|
|
163
136
|
main().catch((error) => {
|
|
164
137
|
console.error("RemoteAgent fatal error:", error);
|
|
165
138
|
releaseProcessLockSync();
|
|
@@ -5,10 +5,10 @@ import path from "node:path";
|
|
|
5
5
|
import { stopSpawnedExecution } from "../adapters/windows-shell.js";
|
|
6
6
|
import { CODEX_USAGE_FALLBACK_MODEL, CodexUsageFallbackService, parseCodexUsageLimit, } from "./codex-usage-fallback-service.js";
|
|
7
7
|
const MODEL_PRESETS = {
|
|
8
|
-
codex: ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.6", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark", "gpt-5.2", "gpt-5.1-codex-max"],
|
|
8
|
+
codex: ["gpt-6-astra", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.6", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark", "gpt-5.2", "gpt-5.1-codex-max"],
|
|
9
9
|
claude: ["sonnet", "opus", "haiku"],
|
|
10
10
|
};
|
|
11
|
-
const DEFAULT_CODEX_MODEL = "gpt-
|
|
11
|
+
const DEFAULT_CODEX_MODEL = "gpt-6-astra";
|
|
12
12
|
export class BridgeService {
|
|
13
13
|
store;
|
|
14
14
|
adapters;
|
|
@@ -367,7 +367,8 @@ export class BridgeService {
|
|
|
367
367
|
return responses.map((response) => {
|
|
368
368
|
const sessionLabel = response.publicSessionId ?? response.sessionId;
|
|
369
369
|
const modelLabel = response.model?.trim() || this.defaultModelFor(response.provider);
|
|
370
|
-
const
|
|
370
|
+
const effortLabel = response.provider === "codex" && modelLabel === "gpt-6-astra" ? " | medium" : "";
|
|
371
|
+
const header = `[${response.provider.toUpperCase()} | ${modelLabel}${effortLabel} | ${sessionLabel}]`;
|
|
371
372
|
return `${header}\n${response.output}`;
|
|
372
373
|
});
|
|
373
374
|
}
|
package/package.json
CHANGED
|
@@ -34,6 +34,12 @@ await fs.chmod(fakeCodex, 0o755);
|
|
|
34
34
|
|
|
35
35
|
const { CodexAdapter } = await import(path.join(root, "dist", "adapters", "codex-adapter.js"));
|
|
36
36
|
const adapter = new CodexAdapter(fakeCodex, 5000, "read-only");
|
|
37
|
+
for (const method of ["buildExecArgs", "buildResumeArgs"]) {
|
|
38
|
+
const args = adapter[method]({model: "gpt-6-astra", cwd: tmp, sessionId: "stream-thread"}, path.join(tmp, "output"), "read-only");
|
|
39
|
+
if (args[args.indexOf("-m") + 1] !== "gpt-6-astra" || !args.some((arg, i) => arg === "-c" && args[i + 1] === 'model_reasoning_effort="medium"')) {
|
|
40
|
+
throw new Error(`Astra medium missing from ${method}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
37
43
|
const progress = [];
|
|
38
44
|
let settled = false;
|
|
39
45
|
const responsePromise = adapter.send({
|
|
@@ -18,7 +18,7 @@ const dataDir = path.join(root, "data");
|
|
|
18
18
|
const workspaceRoot = path.join(root, "workspaces");
|
|
19
19
|
const defaultWorkspace = path.join(root, "default-workspace");
|
|
20
20
|
const fallbackStatePath = path.join(dataDir, "codex-usage-fallback.json");
|
|
21
|
-
const primaryModel = "gpt-
|
|
21
|
+
const primaryModel = "gpt-6-astra";
|
|
22
22
|
const usageError = "You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Aug 27th, 2099 3:52 AM.";
|
|
23
23
|
|
|
24
24
|
try {
|
|
@@ -63,6 +63,7 @@ try {
|
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
let bridge = createBridge();
|
|
66
|
+
assert.equal(bridge.formatResponses([{provider: "codex", model: primaryModel, publicSessionId: "S081", output: "done"}])[0], "[CODEX | gpt-6-astra | medium | S081]\ndone");
|
|
66
67
|
const started = await bridge.startSession("test-bot", "test-chat", "codex");
|
|
67
68
|
const originalSessionId = started.session.sessionId;
|
|
68
69
|
const first = await bridge.routeMessage("test-bot", "test-chat", "first request", async (response) => {
|
|
@@ -12,6 +12,7 @@ const workspaceRoot = path.join(tmp, "workspaces");
|
|
|
12
12
|
const binDir = path.join(tmp, "bin");
|
|
13
13
|
const telegramCalls = path.join(tmp, "telegram-calls.jsonl");
|
|
14
14
|
const capturedDocument = path.join(tmp, "captured-document.ra-secrets");
|
|
15
|
+
const rateLimitOnce = path.join(tmp, "telegram-rate-limit-once");
|
|
15
16
|
|
|
16
17
|
await fs.mkdir(workspace, { recursive: true });
|
|
17
18
|
await fs.mkdir(workspaceRoot, { recursive: true });
|
|
@@ -27,6 +28,7 @@ document_path=""
|
|
|
27
28
|
for arg in "$@"; do
|
|
28
29
|
case "$arg" in
|
|
29
30
|
https://api.telegram.org/bot*/sendMessage) method="sendMessage" ;;
|
|
31
|
+
https://api.telegram.org/bot*/sendChatAction) method="sendChatAction" ;;
|
|
30
32
|
https://api.telegram.org/bot*/editMessageText) method="editMessageText" ;;
|
|
31
33
|
https://api.telegram.org/bot*/deleteMessage) method="deleteMessage" ;;
|
|
32
34
|
https://api.telegram.org/bot*/sendDocument) method="sendDocument" ;;
|
|
@@ -40,6 +42,11 @@ done
|
|
|
40
42
|
text_b64="$(printf '%s' "$text" | base64 -w 0)"
|
|
41
43
|
reply_markup_b64="$(printf '%s' "$reply_markup" | base64 -w 0)"
|
|
42
44
|
printf '%s\\t%s\\t%s\\t%s\\n' "$method" "$chat_id" "$text_b64" "$reply_markup_b64" >> ${JSON.stringify(telegramCalls)}
|
|
45
|
+
if [[ "$method" == "sendMessage" && -n "\${TELEGRAM_SELFTEST_RATE_LIMIT_FILE:-}" && -f "\${TELEGRAM_SELFTEST_RATE_LIMIT_FILE}" ]]; then
|
|
46
|
+
rm -f "\${TELEGRAM_SELFTEST_RATE_LIMIT_FILE}"
|
|
47
|
+
printf '{"ok":false,"error_code":429,"description":"Too Many Requests: retry after 1","parameters":{"retry_after":1}}'
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
43
50
|
case "$method" in
|
|
44
51
|
sendMessage|editMessageText)
|
|
45
52
|
printf '{"ok":true,"result":{"message_id":1001}}'
|
|
@@ -69,6 +76,7 @@ process.env.TELEGRAM_AUTO_PROGRESS_MAX_TURNS = "1";
|
|
|
69
76
|
process.env.TELEGRAM_EMPTY_RESPONSE_RETRIES = "0";
|
|
70
77
|
process.env.TELEGRAM_RETRYABLE_ERROR_RETRIES = "0";
|
|
71
78
|
process.env.LOCAL_UI_ENABLED = "false";
|
|
79
|
+
process.env.TELEGRAM_SELFTEST_RATE_LIMIT_FILE = rateLimitOnce;
|
|
72
80
|
|
|
73
81
|
const [
|
|
74
82
|
{ createBot },
|
|
@@ -320,6 +328,13 @@ await send("/secret set API_TOKEN telegram-secret-export-value");
|
|
|
320
328
|
await send("/secret export REMOTEAGENT_TRANSFER_PASSPHRASE API_TOKEN");
|
|
321
329
|
await send("같은 값을 봐야하는데 로직문제네? 확인해줘\\n이미 수정되어 있을 수 있어.\\n나한테 수정했다고 보고했었거든");
|
|
322
330
|
await send("/state");
|
|
331
|
+
await fs.writeFile(rateLimitOnce, "once", "utf8");
|
|
332
|
+
const rateLimitStartedAt = Date.now();
|
|
333
|
+
await send("/status");
|
|
334
|
+
const rateLimitElapsedMs = Date.now() - rateLimitStartedAt;
|
|
335
|
+
if (rateLimitElapsedMs < 1000) {
|
|
336
|
+
throw new Error(`Telegram retry_after was not honored: elapsedMs=${rateLimitElapsedMs}`);
|
|
337
|
+
}
|
|
323
338
|
|
|
324
339
|
const state = JSON.parse(await fs.readFile(path.join(dataDir, "state.json"), "utf8"));
|
|
325
340
|
const sessions = Object.values(state.sessions);
|
|
@@ -843,6 +858,7 @@ console.log(JSON.stringify({
|
|
|
843
858
|
usageLimitFallback: true,
|
|
844
859
|
longTelegramTextStoredAsFile: true,
|
|
845
860
|
telegramSendMessages: evidenceCalls.filter((call) => call.method === "sendMessage").length,
|
|
861
|
+
telegramRateLimitElapsedMs: rateLimitElapsedMs,
|
|
846
862
|
}, null, 2));
|
|
847
863
|
|
|
848
864
|
process.exit(0);
|