Add Gitea integration for Telegram work mode
This commit is contained in:
53
app/bot.py
53
app/bot.py
@@ -31,6 +31,7 @@ HELP_TEXT = """Telegram-Codex 연결 브리지
|
||||
/whoami - 내 Telegram user_id/chat_id 확인
|
||||
/repo <경로> - /workspaces 아래 작업 폴더 설정
|
||||
/ask <내용> - 내용을 Codex로 전달
|
||||
/work <내용> - 파일 수정, 커밋, 푸시 같은 쓰기 작업 실행
|
||||
/new - 이 채팅의 Codex 세션 초기화
|
||||
/status - 브리지 상태 확인
|
||||
/settings - 모델, 추론강도, 속도 설정 확인
|
||||
@@ -114,6 +115,8 @@ class TelegramCodexBot:
|
||||
app.add_handler(CommandHandler("whoami", self.whoami))
|
||||
app.add_handler(CommandHandler("repo", self.repo))
|
||||
app.add_handler(CommandHandler("ask", self.ask))
|
||||
app.add_handler(CommandHandler("work", self.work))
|
||||
app.add_handler(CommandHandler("write", self.work))
|
||||
app.add_handler(CommandHandler("new", self.new))
|
||||
app.add_handler(CommandHandler("status", self.status))
|
||||
app.add_handler(CommandHandler("settings", self.settings))
|
||||
@@ -233,6 +236,19 @@ class TelegramCodexBot:
|
||||
return
|
||||
await self._run_codex_from_update(update, prompt)
|
||||
|
||||
async def work(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if not await self._guard(update):
|
||||
return
|
||||
prompt = _args_text(context)
|
||||
if not prompt:
|
||||
await self._reply(update, "사용법: /work <파일 수정, 커밋, 푸시 등 작업 내용>")
|
||||
return
|
||||
await self._run_codex_from_update(
|
||||
update,
|
||||
prompt,
|
||||
sandbox=self.config.write_sandbox,
|
||||
)
|
||||
|
||||
async def new(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if not await self._guard(update):
|
||||
return
|
||||
@@ -877,14 +893,19 @@ class TelegramCodexBot:
|
||||
return
|
||||
await self._run_codex_from_update(update, text)
|
||||
|
||||
async def _run_codex_from_update(self, update: Update, prompt: str) -> None:
|
||||
async def _run_codex_from_update(
|
||||
self,
|
||||
update: Update,
|
||||
prompt: str,
|
||||
sandbox: str | None = None,
|
||||
) -> None:
|
||||
chat_id = update.effective_chat.id
|
||||
if update.effective_chat:
|
||||
await update.effective_chat.send_action(ChatAction.TYPING)
|
||||
result, fallback_note = await self._run_codex_for_chat(
|
||||
chat_id=chat_id,
|
||||
prompt=prompt,
|
||||
sandbox=self.config.readonly_sandbox,
|
||||
sandbox=sandbox or self.config.readonly_sandbox,
|
||||
update_chat_state=True,
|
||||
)
|
||||
await self._reply_result(update, result, fallback_note)
|
||||
@@ -929,13 +950,14 @@ class TelegramCodexBot:
|
||||
chat_id=chat_id,
|
||||
chat_state=chat_state,
|
||||
cwd=cwd,
|
||||
sandbox=sandbox,
|
||||
)
|
||||
temp_state = ChatState(
|
||||
repo_path=chat_state.repo_path,
|
||||
session_id=session_id_override or chat_state.session_id,
|
||||
session_backend="app-server" if session_id_override else chat_state.session_backend,
|
||||
)
|
||||
skip_git_repo_check = chat_state.repo_path is None and sandbox == self.config.readonly_sandbox
|
||||
skip_git_repo_check = chat_state.repo_path is None
|
||||
result, backend_used, fallback_note = await self._run_with_backend(
|
||||
chat_id=chat_id,
|
||||
prompt=bridge_prompt,
|
||||
@@ -1127,6 +1149,7 @@ class TelegramCodexBot:
|
||||
chat_id: int,
|
||||
chat_state: ChatState,
|
||||
cwd: Path,
|
||||
sandbox: str,
|
||||
) -> str:
|
||||
thread_id = chat_state.session_id or "(not assigned yet)"
|
||||
schedules = self.state.list_schedules(chat_id=chat_id)
|
||||
@@ -1138,14 +1161,25 @@ class TelegramCodexBot:
|
||||
if not record_lines:
|
||||
record_lines = "- none"
|
||||
runtime_settings = self._format_runtime_settings()
|
||||
gitea_context = self._format_gitea_context()
|
||||
return (
|
||||
"[Telegram bridge context]\n"
|
||||
"You are connected to the user through a private Telegram bridge.\n"
|
||||
f"Default Telegram chat_id for replies, schedules, and notifications: {chat_id}\n"
|
||||
f"Current Codex app-server thread_id: {thread_id}\n"
|
||||
f"Current working directory: {cwd}\n"
|
||||
f"Current sandbox: {sandbox}\n"
|
||||
"Current runtime settings:\n"
|
||||
f"{runtime_settings}\n"
|
||||
"Configured Gitea integration:\n"
|
||||
f"{gitea_context}\n"
|
||||
"If the user asks for repository, issue, branch, or pull-request metadata in Gitea, "
|
||||
"use the gitea_* MCP tools. Never reveal GITEA_TOKEN or print commands that embed it. "
|
||||
"For HTTPS git clone/fetch/push, the container may provide GIT_ASKPASS from the "
|
||||
"configured Gitea environment.\n"
|
||||
"Only edit files, commit, or push when this turn is running with a write-capable "
|
||||
"sandbox, typically from the Telegram /work command. In read-only turns, inspect and "
|
||||
"explain instead of attempting file edits.\n"
|
||||
"If the user asks to schedule, remind, monitor, or notify later, use the "
|
||||
"telegram_create_schedule MCP tool. Use the default chat_id above and do not ask "
|
||||
"for a destination unless the user explicitly wants a different chat. The schedule "
|
||||
@@ -1168,6 +1202,19 @@ class TelegramCodexBot:
|
||||
f"{user_prompt}"
|
||||
)
|
||||
|
||||
def _format_gitea_context(self) -> str:
|
||||
if not self.config.gitea_base_url:
|
||||
return "- not configured"
|
||||
lines = [
|
||||
f"- base_url={self.config.gitea_base_url}",
|
||||
f"- username={self.config.gitea_username or '(not set)'}",
|
||||
f"- email={self.config.gitea_email or '(not set)'}",
|
||||
f"- default_owner={self.config.gitea_default_owner or '(not set)'}",
|
||||
f"- default_repo={self.config.gitea_default_repo or '(not set)'}",
|
||||
f"- token={'configured' if self.config.gitea_token_configured else 'missing'}",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
|
||||
def _should_use_app_server(self, sandbox: str) -> bool:
|
||||
if self.config.codex_backend == "exec":
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user