Add compact command
This commit is contained in:
@@ -55,6 +55,7 @@ journalctl -u codex-tg-bot -f
|
|||||||
|
|
||||||
- любой текст - задача для Codex
|
- любой текст - задача для Codex
|
||||||
- `/new` - новая беседа, сброс текущего `thread_id`
|
- `/new` - новая беседа, сброс текущего `thread_id`
|
||||||
|
- `/compact` - сжать контекст текущего Codex thread
|
||||||
- `/model` - выбор модели и reasoning effort
|
- `/model` - выбор модели и reasoning effort
|
||||||
- `/status` - статус задачи, thread, модели и sandbox
|
- `/status` - статус задачи, thread, модели и sandbox
|
||||||
- `/stop` - отменить текущую задачу
|
- `/stop` - отменить текущую задачу
|
||||||
|
|||||||
@@ -167,15 +167,10 @@ def _codex_config() -> CodexConfig:
|
|||||||
return CodexConfig(codex_bin=config.CODEX_BIN)
|
return CodexConfig(codex_bin=config.CODEX_BIN)
|
||||||
|
|
||||||
|
|
||||||
async def _get_thread(
|
def _thread_kwargs(model: str | None, effort: str | None) -> dict[str, Any]:
|
||||||
codex: AsyncCodex,
|
|
||||||
thread_id: str | None,
|
|
||||||
model: str | None,
|
|
||||||
effort: str | None,
|
|
||||||
) -> tuple[Any, bool]:
|
|
||||||
selected_model = model or config.CODEX_DEFAULT_MODEL
|
selected_model = model or config.CODEX_DEFAULT_MODEL
|
||||||
thread_config = {"model_reasoning_effort": effort} if effort else None
|
thread_config = {"model_reasoning_effort": effort} if effort else None
|
||||||
kwargs = {
|
return {
|
||||||
"approval_mode": _approval_mode(),
|
"approval_mode": _approval_mode(),
|
||||||
"config": thread_config,
|
"config": thread_config,
|
||||||
"cwd": config.WORK_DIR,
|
"cwd": config.WORK_DIR,
|
||||||
@@ -183,6 +178,15 @@ async def _get_thread(
|
|||||||
"model": selected_model,
|
"model": selected_model,
|
||||||
"sandbox": _sandbox(),
|
"sandbox": _sandbox(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_thread(
|
||||||
|
codex: AsyncCodex,
|
||||||
|
thread_id: str | None,
|
||||||
|
model: str | None,
|
||||||
|
effort: str | None,
|
||||||
|
) -> tuple[Any, bool]:
|
||||||
|
kwargs = _thread_kwargs(model, effort)
|
||||||
if thread_id:
|
if thread_id:
|
||||||
try:
|
try:
|
||||||
return await codex.thread_resume(thread_id, **kwargs), True
|
return await codex.thread_resume(thread_id, **kwargs), True
|
||||||
@@ -284,3 +288,17 @@ async def run_task(
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
yield _done_from_turn(completed_turn, thread.id, items, usage)
|
yield _done_from_turn(completed_turn, thread.id, items, usage)
|
||||||
|
|
||||||
|
|
||||||
|
async def compact_thread(
|
||||||
|
thread_id: str,
|
||||||
|
model: str | None = None,
|
||||||
|
effort: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Start compaction for an existing Codex thread."""
|
||||||
|
async with AsyncCodex(config=_codex_config()) as codex:
|
||||||
|
if config.OPENAI_API_KEY:
|
||||||
|
await codex.login_api_key(config.OPENAI_API_KEY)
|
||||||
|
|
||||||
|
thread = await codex.thread_resume(thread_id, **_thread_kwargs(model, effort))
|
||||||
|
await thread.compact()
|
||||||
|
|||||||
36
bot/main.py
36
bot/main.py
@@ -57,6 +57,7 @@ HELP_TEXT = (
|
|||||||
"Контекст беседы сохраняется между сообщениями в этом чате.\n\n"
|
"Контекст беседы сохраняется между сообщениями в этом чате.\n\n"
|
||||||
"Команды:\n"
|
"Команды:\n"
|
||||||
"/new - начать новую беседу (сбросить контекст)\n"
|
"/new - начать новую беседу (сбросить контекст)\n"
|
||||||
|
"/compact - сжать контекст текущего thread\n"
|
||||||
"/model - выбрать модель и уровень reasoning effort\n"
|
"/model - выбрать модель и уровень reasoning effort\n"
|
||||||
"/status - статус текущей задачи и thread\n"
|
"/status - статус текущей задачи и thread\n"
|
||||||
"/stop - отменить выполняющуюся задачу\n"
|
"/stop - отменить выполняющуюся задачу\n"
|
||||||
@@ -118,6 +119,39 @@ async def cmd_new(_, message: Message):
|
|||||||
await message.reply_text("Контекста и не было - беседа новая.")
|
await message.reply_text("Контекста и не было - беседа новая.")
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_message(filters.command("compact") & admin)
|
||||||
|
async def cmd_compact(_, message: Message):
|
||||||
|
chat_id = message.chat.id
|
||||||
|
task = running_tasks.get(chat_id)
|
||||||
|
if task and not task.done():
|
||||||
|
await message.reply_text(
|
||||||
|
"Сейчас выполняется задача. Дождитесь завершения или отмените ее через /stop."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
thread_id = chats.get(chat_id, "thread_id")
|
||||||
|
if not thread_id:
|
||||||
|
await message.reply_text("В этом чате еще нет сохраненного Codex thread.")
|
||||||
|
return
|
||||||
|
|
||||||
|
progress = await message.reply_text("Сжимаю контекст thread...")
|
||||||
|
try:
|
||||||
|
await codex_runner.compact_thread(
|
||||||
|
thread_id,
|
||||||
|
model=chats.get(chat_id, "model"),
|
||||||
|
effort=chats.get(chat_id, "effort"),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
log.exception("Compact failed in chat %s", chat_id)
|
||||||
|
await progress.edit_text("Не удалось запустить compact, подробности в логах бота.")
|
||||||
|
return
|
||||||
|
|
||||||
|
await progress.edit_text(
|
||||||
|
f"Compact запущен для thread `{thread_id[:8]}...`",
|
||||||
|
parse_mode=ParseMode.MARKDOWN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(filters.command("model") & admin)
|
@app.on_message(filters.command("model") & admin)
|
||||||
async def cmd_model(_, message: Message):
|
async def cmd_model(_, message: Message):
|
||||||
await message.reply_text(
|
await message.reply_text(
|
||||||
@@ -177,7 +211,7 @@ async def cmd_stop(_, message: Message):
|
|||||||
|
|
||||||
@app.on_message(
|
@app.on_message(
|
||||||
filters.text
|
filters.text
|
||||||
& ~filters.command(["start", "help", "new", "model", "status", "stop"])
|
& ~filters.command(["start", "help", "new", "compact", "model", "status", "stop"])
|
||||||
& admin
|
& admin
|
||||||
)
|
)
|
||||||
async def on_task(client: Client, message: Message):
|
async def on_task(client: Client, message: Message):
|
||||||
|
|||||||
Reference in New Issue
Block a user