From 7f2d092c9549d695d1aaa223dd92230db73452dc Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 12 Jun 2026 17:30:06 +0100 Subject: [PATCH] refac --- cptr/utils/ai.py | 10 ++++++++-- cptr/utils/bridge.py | 16 +++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/cptr/utils/ai.py b/cptr/utils/ai.py index b444dcd..7845eb2 100644 --- a/cptr/utils/ai.py +++ b/cptr/utils/ai.py @@ -12,6 +12,7 @@ from __future__ import annotations import asyncio import json import logging +import uuid from collections.abc import AsyncIterator from typing import Dict, List @@ -501,11 +502,16 @@ def _to_responses_input(messages: list[dict], instructions: str) -> list[dict]: elif role == "assistant" and m.get("tool_calls"): for tc in m["tool_calls"]: args = tc["function"].get("arguments", "{}") + call_id = tc.get("id", "") + # Responses API requires id to start with "fc_" + fc_id = tc.get("fc_id", "") + if not fc_id or not fc_id.startswith("fc_"): + fc_id = f"fc_{call_id.replace('call_', '', 1) or uuid.uuid4().hex}" items.append( { "type": "function_call", - "id": tc.get("fc_id", tc.get("id", "")), - "call_id": tc.get("id", ""), + "id": fc_id, + "call_id": call_id, "name": tc["function"]["name"], "arguments": args if isinstance(args, str) else json.dumps(args), "status": "completed", diff --git a/cptr/utils/bridge.py b/cptr/utils/bridge.py index 4127ffd..32b1772 100644 --- a/cptr/utils/bridge.py +++ b/cptr/utils/bridge.py @@ -174,15 +174,18 @@ async def delete_bot_config(bot_id: str) -> bool: async def find_chat_for_thread(bot_id: str, external_thread_id: str) -> str | None: - """Find an existing cptr chat_id for a platform thread. + """Find the most recent cptr chat_id for a platform thread. - Scans chats with matching bridge metadata. This is fine for the - small number of active bridge threads (typically < 100). + Scans chats with matching bridge metadata and returns the newest one, + so /new (which creates a new chat with the same thread ID) takes effect. """ from cptr.models import Chat from cptr.utils.db import get_db from sqlalchemy import select + best_id = None + best_ts = -1 + async with await get_db() as db: result = await db.execute( select(Chat).where(Chat.user_id.isnot(None)) @@ -193,8 +196,11 @@ async def find_chat_for_thread(bot_id: str, external_thread_id: str) -> str | No meta.get("bridge_bot_id") == bot_id and meta.get("bridge_external_thread_id") == external_thread_id ): - return chat.id - return None + ts = getattr(chat, "created_at", 0) or 0 + if ts > best_ts: + best_ts = ts + best_id = chat.id + return best_id # ── BotManager ───────────────────────────────────────────────