Add Gitea integration for Telegram work mode

This commit is contained in:
2026-06-09 13:50:23 +09:00
parent 5a2c5df041
commit c7652d3ada
10 changed files with 656 additions and 5 deletions

View File

@@ -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