ltcai 2.2.2 → 2.2.7

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.
@@ -4,14 +4,14 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
6
6
  <title>Lattice AI Workspace OS</title>
7
- <script src="/static/scripts/ux.js?v=2.2.2"></script>
7
+ <script src="/static/scripts/ux.js?v=2.2.7"></script>
8
8
  <link rel="manifest" href="/manifest.json">
9
9
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
10
10
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap">
11
11
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/tabler-icons.min.css">
12
- <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.2">
13
- <link rel="stylesheet" href="/static/workspace.css?v=2.2.2">
14
- <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.2">
12
+ <link rel="stylesheet" href="/static/css/tokens.css?v=2.2.7">
13
+ <link rel="stylesheet" href="/static/workspace.css?v=2.2.7">
14
+ <link rel="stylesheet" href="/static/css/responsive.css?v=2.2.7">
15
15
  </head>
16
16
  <body>
17
17
  <div class="workspace-shell">
@@ -333,6 +333,6 @@
333
333
  </div>
334
334
 
335
335
  <div class="toast" id="toast"></div>
336
- <script src="/static/scripts/workspace.js?v=1.7.0"></script>
336
+ <script src="/static/scripts/workspace.js?v=2.2.7"></script>
337
337
  </body>
338
338
  </html>
package/telegram_bot.py CHANGED
@@ -11,6 +11,10 @@ import zipfile
11
11
  import json
12
12
  from pathlib import Path
13
13
 
14
+ from latticeai.core.logging_safety import install_sensitive_log_filter, safe_log_text
15
+
16
+ install_sensitive_log_filter()
17
+
14
18
  def load_env_file(path=".env"):
15
19
  env_path = Path(path)
16
20
  if not env_path.exists():
@@ -98,7 +102,7 @@ def load_chat_ids():
98
102
  data = json.loads(CHAT_IDS_FILE.read_text(encoding="utf-8"))
99
103
  return {int(cid) for cid in data.get("chat_ids", [])}
100
104
  except Exception as e:
101
- logger.error("텔레그램 채팅 목록 로드 실패: %s", e)
105
+ logger.error("텔레그램 채팅 목록 로드 실패: %s", safe_log_text(e))
102
106
  return set()
103
107
 
104
108
  def save_chat_ids(chat_ids):
@@ -108,7 +112,7 @@ def save_chat_ids(chat_ids):
108
112
  encoding="utf-8",
109
113
  )
110
114
  except Exception as e:
111
- logger.error("텔레그램 채팅 목록 저장 실패: %s", e)
115
+ logger.error("텔레그램 채팅 목록 저장 실패: %s", safe_log_text(e))
112
116
 
113
117
  def register_chat_id(chat_id):
114
118
  chat_ids = load_chat_ids()
@@ -129,7 +133,7 @@ async def send_message(client, chat_id, text, reply_markup=None):
129
133
  payload["reply_markup"] = reply_markup
130
134
  await client.post(url, json=payload)
131
135
  except Exception as e:
132
- logger.error("메시지 전송 실패: %s", e)
136
+ logger.error("메시지 전송 실패: %s", safe_log_text(e))
133
137
 
134
138
  async def send_photo(client, chat_id, file_path: Path, caption: str = ""):
135
139
  url = f"{API_URL}/sendPhoto"
@@ -140,8 +144,8 @@ async def send_photo(client, chat_id, file_path: Path, caption: str = ""):
140
144
  if res.status_code != 200:
141
145
  await send_message(client, chat_id, f"사진 전송 실패 ({res.status_code})")
142
146
  except Exception as e:
143
- logger.error("사진 전송 실패: %s", e)
144
- await send_message(client, chat_id, f"사진 전송 오류: {e}")
147
+ logger.error("사진 전송 실패: %s", safe_log_text(e))
148
+ await send_message(client, chat_id, f"사진 전송 오류: {safe_log_text(e)}")
145
149
 
146
150
  async def send_document(client, chat_id, file_path, caption=None, filename=None):
147
151
  url = f"{API_URL}/sendDocument"
@@ -154,9 +158,9 @@ async def send_document(client, chat_id, file_path, caption=None, filename=None)
154
158
  timeout=300.0,
155
159
  )
156
160
  if res.status_code != 200:
157
- logger.error("파일 전송 실패 (%s): %s", res.status_code, res.text)
161
+ logger.error("파일 전송 실패 (%s): %s", res.status_code, safe_log_text(res.text))
158
162
  except Exception as e:
159
- logger.error("파일 전송 실패: %s", e)
163
+ logger.error("파일 전송 실패: %s", safe_log_text(e))
160
164
 
161
165
  async def send_chat_action(client, chat_id, action="typing"):
162
166
  try:
@@ -247,7 +251,7 @@ async def download_telegram_file(client, file_id) -> bytes | None:
247
251
  dl = await client.get(f"https://api.telegram.org/file/bot{TOKEN}/{file_path}")
248
252
  return dl.content if dl.status_code == 200 else None
249
253
  except Exception as e:
250
- logger.error("파일 다운로드 실패: %s", e)
254
+ logger.error("파일 다운로드 실패: %s", safe_log_text(e))
251
255
  return None
252
256
 
253
257
  async def download_as_base64(client, file_id) -> str | None:
@@ -509,7 +513,7 @@ async def send_web_link(client, chat_id):
509
513
  async with _server_client() as lc:
510
514
  await lc.post(f"{API_URL}/sendMessage", json=payload)
511
515
  except Exception as e:
512
- logger.error("웹 링크 전송 실패: %s", e)
516
+ logger.error("웹 링크 전송 실패: %s", safe_log_text(e))
513
517
 
514
518
  # ── MCP tools ─────────────────────────────────────────────────────────────────
515
519
 
@@ -760,7 +764,7 @@ async def handle_plan_callback(client, chat_id, data: str) -> None:
760
764
  async def process_ai_request(client, chat_id, user_text, image_data=None):
761
765
  try:
762
766
  await send_chat_action(client, chat_id, "upload_photo" if image_data else "typing")
763
- logger.info("ask_ai 호출 시작: chat_id=%s text=%r", chat_id, user_text[:30])
767
+ logger.info("ask_ai 호출 시작: chat_id=%s text=%r", chat_id, safe_log_text(user_text[:30]))
764
768
  data = await ask_ai(client, user_text, image_data, agent_mode=not image_data)
765
769
  logger.info("ask_ai 완료: chat_id=%s result_keys=%s", chat_id, list(data.keys()) if isinstance(data, dict) else type(data))
766
770
 
@@ -777,7 +781,7 @@ async def process_ai_request(client, chat_id, user_text, image_data=None):
777
781
  await send_generated_files(client, chat_id, collect_generated_files(data))
778
782
  await send_preview_links(client, chat_id, collect_preview_urls(data))
779
783
  except Exception as e:
780
- logger.error("process_ai_request 실패 (chat_id=%s): %s", chat_id, e, exc_info=True)
784
+ logger.error("process_ai_request 실패 (chat_id=%s): %s", chat_id, safe_log_text(e), exc_info=True)
781
785
  try:
782
786
  await send_message(client, chat_id, "⚠️ 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.")
783
787
  except Exception:
@@ -916,7 +920,7 @@ async def run_bot():
916
920
  updates = await get_updates(client, last_update_id)
917
921
  retry_delay = 1
918
922
  except Exception as e:
919
- logger.error("get_updates 실패: %s", e)
923
+ logger.error("get_updates 실패: %s", safe_log_text(e))
920
924
  await asyncio.sleep(min(retry_delay, 30))
921
925
  retry_delay = min(retry_delay * 2, 30)
922
926
  continue
@@ -997,13 +1001,13 @@ async def run_bot():
997
1001
  task.add_done_callback(_log_task_exception)
998
1002
 
999
1003
  except Exception as e:
1000
- logger.error("업데이트 처리 중 예외: %s", e)
1004
+ logger.error("업데이트 처리 중 예외: %s", safe_log_text(e))
1001
1005
 
1002
1006
  await asyncio.sleep(0.5)
1003
1007
 
1004
1008
  def _log_task_exception(task):
1005
1009
  if not task.cancelled() and task.exception():
1006
- logger.error("백그라운드 태스크 예외: %s", task.exception())
1010
+ logger.error("백그라운드 태스크 예외: %s", safe_log_text(task.exception()))
1007
1011
 
1008
1012
  if __name__ == "__main__":
1009
1013
  try: