fix: SQLite 싱글톤 연결 I/O 에러 수정 + clawdbot 모델 오버라이드
- dbsetup: get_sqlite_connection()에 SELECT 1 헬스체크 추가 (죽은 연결 자동 재생성) - pos_sales_gui: 싱글톤 SQLite conn.close() 제거 (I/O closed file 에러 원인) - qr_token_generator: DatabaseManager() 새 생성 → 전역 db_manager 싱글톤 사용 - clawdbot_client: model 파라미터 추가, 업셀링에 claude-sonnet-4-5 지정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4c3e1d08b2
commit
db5f6063ec
@ -193,6 +193,13 @@ class DatabaseManager:
|
||||
Returns:
|
||||
sqlite3.Connection: SQLite 연결 객체
|
||||
"""
|
||||
# 연결이 닫혀있으면 재생성
|
||||
if self.sqlite_conn is not None:
|
||||
try:
|
||||
self.sqlite_conn.execute("SELECT 1")
|
||||
except Exception:
|
||||
self.sqlite_conn = None
|
||||
|
||||
if self.sqlite_conn is None:
|
||||
# 파일 존재 여부 확인
|
||||
is_new_db = not self.sqlite_db_path.exists()
|
||||
|
||||
@ -181,8 +181,7 @@ class SalesQueryThread(QThread):
|
||||
finally:
|
||||
if mssql_conn:
|
||||
mssql_conn.close()
|
||||
if sqlite_conn:
|
||||
sqlite_conn.close()
|
||||
# sqlite_conn은 싱글톤이므로 닫지 않음 (닫으면 다른 곳에서 I/O 에러 발생)
|
||||
|
||||
|
||||
class QRGeneratorThread(QThread):
|
||||
@ -600,9 +599,7 @@ class UserMileageDialog(QDialog):
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '오류', f'회원 정보 조회 실패:\n{str(e)}')
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
# conn은 싱글톤이므로 닫지 않음
|
||||
|
||||
|
||||
class POSSalesGUI(QMainWindow):
|
||||
|
||||
@ -45,7 +45,7 @@ def _load_gateway_config():
|
||||
|
||||
|
||||
async def _ask_gateway(message, session_id='pharmacy-upsell',
|
||||
system_prompt=None, timeout=60):
|
||||
system_prompt=None, timeout=60, model=None):
|
||||
"""
|
||||
Clawdbot Gateway WebSocket API 호출
|
||||
|
||||
@ -112,7 +112,29 @@ async def _ask_gateway(message, session_id='pharmacy-upsell',
|
||||
return None
|
||||
break # 연결 성공
|
||||
|
||||
# 4. agent 요청
|
||||
# 4. 모델 오버라이드 (sessions.patch)
|
||||
if model:
|
||||
patch_id = str(uuid.uuid4())
|
||||
patch_frame = {
|
||||
'type': 'req',
|
||||
'id': patch_id,
|
||||
'method': 'sessions.patch',
|
||||
'params': {
|
||||
'key': session_id,
|
||||
'model': model,
|
||||
}
|
||||
}
|
||||
await ws.send(json.dumps(patch_frame))
|
||||
# patch 응답 대기
|
||||
while True:
|
||||
msg = await asyncio.wait_for(ws.recv(), timeout=10)
|
||||
data = json.loads(msg)
|
||||
if data.get('id') == patch_id:
|
||||
if not data.get('ok'):
|
||||
logger.warning(f"[Clawdbot] sessions.patch 실패: {data.get('error', {}).get('message', 'unknown')}")
|
||||
break
|
||||
|
||||
# 5. agent 요청
|
||||
agent_id = str(uuid.uuid4())
|
||||
agent_params = {
|
||||
'message': message,
|
||||
@ -174,7 +196,7 @@ async def _ask_gateway(message, session_id='pharmacy-upsell',
|
||||
|
||||
|
||||
def ask_clawdbot(message, session_id='pharmacy-upsell',
|
||||
system_prompt=None, timeout=60):
|
||||
system_prompt=None, timeout=60, model=None):
|
||||
"""
|
||||
동기 래퍼: Flask에서 직접 호출 가능
|
||||
|
||||
@ -183,6 +205,7 @@ def ask_clawdbot(message, session_id='pharmacy-upsell',
|
||||
session_id: 세션 ID (대화 구분용)
|
||||
system_prompt: 추가 시스템 프롬프트
|
||||
timeout: 타임아웃 (초)
|
||||
model: 모델 오버라이드 (예: 'anthropic/claude-sonnet-4-5')
|
||||
|
||||
Returns:
|
||||
str: AI 응답 텍스트 (실패 시 None)
|
||||
@ -190,7 +213,7 @@ def ask_clawdbot(message, session_id='pharmacy-upsell',
|
||||
try:
|
||||
loop = asyncio.new_event_loop()
|
||||
result = loop.run_until_complete(
|
||||
_ask_gateway(message, session_id, system_prompt, timeout)
|
||||
_ask_gateway(message, session_id, system_prompt, timeout, model=model)
|
||||
)
|
||||
loop.close()
|
||||
return result
|
||||
@ -201,6 +224,8 @@ def ask_clawdbot(message, session_id='pharmacy-upsell',
|
||||
|
||||
# 업셀링 전용 ──────────────────────────────────────
|
||||
|
||||
UPSELL_MODEL = 'anthropic/claude-sonnet-4-5' # 업셀링은 Sonnet (빠르고 충분)
|
||||
|
||||
UPSELL_SYSTEM_PROMPT = """당신은 동네 약국(청춘약국)의 친절한 약사입니다.
|
||||
고객의 구매 이력을 보고, 자연스럽고 따뜻한 톤으로 약 하나를 추천합니다.
|
||||
강압적이거나 광고 같은 느낌이 아닌, 진심으로 건강을 걱정하는 약사의 말투로 작성해주세요.
|
||||
@ -238,7 +263,8 @@ def generate_upsell(user_name, current_items, recent_products):
|
||||
prompt,
|
||||
session_id=f'upsell-{user_name}',
|
||||
system_prompt=UPSELL_SYSTEM_PROMPT,
|
||||
timeout=30
|
||||
timeout=30,
|
||||
model=UPSELL_MODEL
|
||||
)
|
||||
|
||||
if not response_text:
|
||||
@ -285,7 +311,8 @@ def generate_upsell_real(user_name, current_items, recent_products, available_pr
|
||||
prompt,
|
||||
session_id=f'upsell-real-{user_name}',
|
||||
system_prompt=UPSELL_REAL_SYSTEM_PROMPT,
|
||||
timeout=30
|
||||
timeout=30,
|
||||
model=UPSELL_MODEL
|
||||
)
|
||||
|
||||
if not response_text:
|
||||
|
||||
@ -115,8 +115,8 @@ def save_token_to_db(transaction_id, token_hash, total_amount, claimable_points,
|
||||
- token_hash가 이미 존재하면 실패 (UNIQUE 제약)
|
||||
"""
|
||||
try:
|
||||
db_manager = DatabaseManager()
|
||||
conn = db_manager.get_sqlite_connection()
|
||||
from db.dbsetup import db_manager as _db_manager
|
||||
conn = _db_manager.get_sqlite_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 중복 체크 (transaction_id)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user