- Telegram update ingestion (webhook + polling)
- Job queue + lease/retry orchestration on PostgreSQL
- CLI provider execution (
codex,gemini,claude,echo) - Real-time event streaming back to Telegram
- Multi-bot supervisor and local mock messenger for full offline testing
처음 실행한 뒤, 아래 순서대로 하면 신규 기능(/talk, /relay~/court)을 바로 체험할 수 있습니다.
./scripts/run-local-multibot.sh start- 기본 URL:
http://127.0.0.1:9082/_mock/ui - 왼쪽
Multi Bots에서 필요한 수만큼 봇을 선택합니다. /court는 반드시 3개 이상 봇을 선택해야 합니다.
- 아래 2곳 모두 동일하게 동작합니다.
- Timeline 입력창(
message-input) - 왼쪽 병렬 입력창(
parallel-message-input)
- Timeline 입력창(
/talk 오늘은 뭐 만들까? --rounds 1
/relay 퇴근길 지하철에서 생긴 일 --rounds 1
/pitchbattle 주말 사이드 프로젝트 아이디어 --rounds 1
/quizbattle 한국사 상식 --rounds 1
/debate-lite 원격근무 vs 오피스근무 --rounds 1
/improv 우주 엘리베이터에서 길을 잃은 팀 --rounds 1
/quest 30분 안에 랜딩 페이지 초안 완성 --rounds 1
/memechain 재택근무 현실 --rounds 1
/court 버그 배포 사고 책임 공방 --rounds 1
| 명령어 | 모드 성격 | 결과 스타일(1라운드) | 추천 용도 |
|---|---|---|---|
/talk 오늘은 뭐 만들까? --rounds 1 |
자유 대화 | 가볍게 아이디어를 던지고 빠르게 정리 | 워밍업, 브레인스토밍 시작 |
/relay 퇴근길 지하철에서 생긴 일 --rounds 1 |
릴레이 스토리 | 앞 발화를 이어 다음 장면 생성 | 스토리 이어쓰기, 콘텐츠 초안 |
/pitchbattle 주말 사이드 프로젝트 아이디어 --rounds 1 |
피치 대결 | 짧은 설득형 아이디어 제시 | 아이디어 비교, 후보 압축 |
/quizbattle 한국사 상식 --rounds 1 |
퀴즈 대결 | 문제/답변 흐름으로 지식 점검 | 학습용 퀴즈, 팀 아이스브레이킹 |
/debate-lite 원격근무 vs 오피스근무 --rounds 1 |
경량 찬반 토론 | 찬반 논지 + 핵심 근거 제시 | 의사결정 전 관점 점검 |
/improv 우주 엘리베이터에서 길을 잃은 팀 --rounds 1 |
즉흥극 | 캐릭터 몰입형 상황 전개 | 창의 글쓰기, 세계관 확장 |
/quest 30분 안에 랜딩 페이지 초안 완성 --rounds 1 |
협동 미션 | 진행 상태 + 다음 액션 중심 | 실무 태스크 kickoff |
/memechain 재택근무 현실 --rounds 1 |
밈 체인 | 짧고 리듬감 있는 밈 연쇄 | 소셜 카피, 가벼운 콘텐츠 |
/court 버그 배포 사고 책임 공방 --rounds 1 |
법정 공방 롤플레이 | 검사/변호/증인형 논리 공방 | 이슈 회고, 책임/원인 구조화 |
--rounds <n>: 라운드 수 (1~8)--max-turn-sec <n>: 턴 최대 대기 시간 (10~240)--keep-session:/new를 생략하고 현재 세션 유지
Parallel Results: 각 턴/명령의 PASS/FAIL 요약- 상단
Talk / Play Viewer: 대화/플레이 로그 전체 흐름
알 수 없는 옵션에러: 지원 옵션(--rounds,--max-turn-sec,--keep-session)만 사용- 오래 걸림:
--rounds 1,--max-turn-sec 20~45로 먼저 테스트 - 활성 run 충돌:
/stop후 재시도 - 판정 표시가
[판정 실패]: 봇 응답에WINNER:,VERDICT:,RESULT:형식이 없는 경우
상세 운영 가이드는 docs/play_commands_manual.md를 참고하세요.
- 빠른 사용 가이드 (Talk/Play 기능)
- 특징
- 1. Project Summary
- 2. Architecture
- 3. Runtime Modes
- 4. Tech Stack
- 5. Quick Start
- 6. Configuration
- 7. Run Guide
- 8. Mock Messenger Guide
- 9. Telegram Command Reference
- 10. API Endpoints
- 11. Data Model and Queue States
- 12. Metrics and Observability
- 13. Test Strategy
- 14. Script Catalog
- 15. Troubleshooting
- 16. License
- 각 봇은 기본적으로
/mode명령으로gemini,codex,claude모드를 전환할 수 있고, 대시보드 봇 카드에서 provider/model 드롭다운으로 즉시 변경할 수 있습니다. - Codex 기본 모델은
gpt-5.4이며, 대시보드와/model명령에서gpt-5.4,gpt-5.3-codex,gpt-5.3-codex-spark,gpt-5.2-codex,gpt-5.1-codex-max,gpt-5.2,gpt-5.1-codex-mini,gpt-5를 선택할 수 있습니다. - 멀티봇을 지원하여, 한 번의 프롬프트로 여러 봇에서 다양한 형태의 결과물을 병렬로 얻을 수 있습니다.
- Session 섹션에서
Project / Skill / Role(controller/planner/executor/integrator)를 통합 제어할 수 있고, 병렬 입력창에서/cowork <요청>으로 역할 기반 협업 오케스트레이션을 실행할 수 있습니다. - Mock Dashboard UI에서는
/talk외에/relay,/pitchbattle,/quizbattle,/debate-lite,/improv,/quest,/memechain,/courtPlay 명령 8종을 즉시 실행할 수 있습니다. - 좌측
Parallel Results / Debate Panel / Cowork Panel / Control Tower는 동일한 접기/펼치기 UX를 제공하며, 펼친 상태가 많아지면 사이드바 전체에서 스크롤됩니다. - 멀티봇은 동적으로 다수 생성 및 삭제가 가능합니다.
- 대시보드를 제공하여 시뮬레이션과 다양한 추가 개발 테스트를 수행할 수 있습니다.
- Telegram 연동 코드는 구현되어 있으나, 현재 Telegram 계정 부재로 실계정 연동 테스트는 아직 진행하지 않았습니다.
이 프로젝트는 Telegram 메시지를 CLI 에이전트 실행으로 연결하는 브리지입니다. 핵심은 다음 4단계입니다.
- Telegram 업데이트 수신 (webhook/polling)
- DB 기반 큐에 작업 적재
- 워커가 CLI provider 실행 + 이벤트/아티팩트 수집
- 결과를 Telegram으로 스트리밍 전송 + 세션 요약 누적
현재 구조는 MVP이지만, 멀티봇/장애복구/로컬 테스트 자동화까지 포함되어 운영 검증에 유리합니다.
flowchart LR
U[Telegram User] --> TG[Telegram API or Mock API]
TG --> IN[Ingress: webhook or poller]
IN --> TU[(telegram_updates)]
TU --> TUJ[(telegram_update_jobs)]
TUJ --> UW[update_worker]
UW --> CMD[TelegramCommandHandler]
CMD --> T[(turns)]
T --> RJ[(cli_run_jobs)]
RJ --> RW[run_worker]
RW --> AD[CLI Adapter: codex/gemini/claude/echo]
AD --> EV[(cli_events)]
EV --> ST[TelegramEventStreamer]
ST --> TG
RW --> SS[SummaryService]
SS --> S[(sessions + session_summaries)]
- Lease 기반 워커 처리
telegram_update_jobs,cli_run_jobs를FOR UPDATE SKIP LOCKED로 lease 처리- 워커 재시작/크래시 시 lease 만료 후 재처리 가능
- 중복 제어
(bot_id, update_id)중복 차단- 활성 run/session 유니크 인덱스로 동시성 보호
- 세션 연속성
- provider thread id 저장 + rolling summary 누적
- provider 전환 시 thread는 reset, summary 기반 문맥은 유지
- 실시간 스트리밍
- 이벤트를
cli_events에 영속화 - Telegram 메시지 edit + continuation 전략으로 장문 대응
- 이벤트를
- 봇당 1프로세스
- 각 프로세스가 API + workers를 같이 수행
- 엔드포인트:
/healthz,/readyz,/metrics,/telegram/webhook/{bot_id}/{path_secret}
- 공유 webhook API 1개 + gateway bot마다 worker-only 프로세스
- API/worker 분리 운영에 유리
- gateway API는 모든 gateway bot webhook을 수신해서 큐에 적재
- Python 3.11+
- FastAPI + Uvicorn
- SQLAlchemy 2 + asyncpg
- PostgreSQL (운영 큐/상태 저장소)
- httpx (Telegram API / 외부 요청)
- PyYAML + pydantic-settings
- pytest + pytest-asyncio
- Playwright (mock UI E2E)
docker compose up -d postgres
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
cp config/bots.example.yaml config/bots.yaml.\scripts\bootstrap-local.ps1python -m telegram_bot_new.main supervisor| Key | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | - | PostgreSQL async URL |
LOG_LEVEL |
No | INFO |
로그 레벨 |
JOB_LEASE_MS |
No | 30000 |
잡 lease 기간 |
WORKER_POLL_INTERVAL_MS |
No | 250 |
워커 poll 주기 |
RUN_TURN_TIMEOUT_SEC |
No | 90 |
단일 turn watchdog timeout(초, 최소 15) |
SUPERVISOR_RESTART_MAX_BACKOFF_SEC |
No | 30 |
supervisor 재시작 백오프 상한 |
TELEGRAM_API_BASE_URL |
No | https://api.telegram.org |
Telegram base URL (mock 사용 시 로컬 주소) |
TELEGRAM_VIRTUAL_TOKEN |
No | mock_token_1 |
mock 토큰 자동 fallback |
TELEGRAM_BOT_TOKEN |
No | empty | env-only bootstrap 토큰 |
TELEGRAM_OWNER_USER_ID |
No | empty | owner-only 접근 제어 |
TELEGRAM_BOT_ID |
No | bot-1 |
env-only bootstrap bot id |
TELEGRAM_BOT_NAME |
No | Bot 1 |
env-only bootstrap bot name |
TELEGRAM_BOT_MODE |
No | embedded |
env-only bootstrap mode |
TELEGRAM_WEBHOOK_PUBLIC_URL |
No | empty | webhook URL (없으면 polling) |
TELEGRAM_WEBHOOK_PATH_SECRET |
No | empty | webhook path secret |
TELEGRAM_WEBHOOK_SECRET_TOKEN |
No | empty | webhook secret token |
BOT_SKILLS_DIR |
No | empty | skill 루트 경로(기본 ./skills) |
STRICT_BOT_DB_ISOLATION |
No | false |
멀티봇에서 bot별 database_url 강제 여부 |
최소 설정:
bots:
- telegram_token: TELEGRAM_BOT_TOKEN상세 설정 예시:
bots:
- bot_id: bot-a
name: Bot A
mode: embedded
telegram_token: "123456:abc"
owner_user_id: 111111111
adapter: gemini
webhook:
path_secret: bot-a-path
secret_token: bot-a-secret
public_url: https://example.com/telegram/webhook/bot-a/bot-a-path
codex:
model: gpt-5.4
sandbox: workspace-write
gemini:
model: gemini-2.5-pro
claude:
model: claude-sonnet-4-5telegram_token: TELEGRAM_BOT_TOKEN이면.env의TELEGRAM_BOT_TOKEN대체- 토큰이 비어 있고
TELEGRAM_API_BASE_URL이 로컬 mock 주소면TELEGRAM_VIRTUAL_TOKEN자동 사용 owner_user_id가 비어 있으면 누구나 접근 가능
provider CLI는 기본적으로 시스템 PATH에서 찾지만, 아래 환경 변수로 명시적으로 고정할 수 있습니다.
CODEX_BINGEMINI_BINCLAUDE_BIN
추가로 codex는 PATH에 없더라도 VS Code / ChatGPT extension에 포함된 번들 바이너리를 자동 탐색하는 fallback 로직이 있습니다.
python -m telegram_bot_new.main supervisor
python -m telegram_bot_new.main run-bot --bot-id bot-1
python -m telegram_bot_new.main run-gateway --config config/bots.yaml --host 0.0.0.0 --port 4312telegram-bot-new supervisor
telegram-bot-new-mock --host 127.0.0.1 --port 9082mock에서 webhook 등록 상태에서도 polling 기반 getUpdates를 허용해야 하면 다음 옵션을 사용할 수 있습니다.
telegram-bot-new-mock --allow-get-updates-with-webhook.\scripts\run-local.ps1 -Mode supervisor
.\scripts\run-local.ps1 -Mode run-bot -BotId bot-1
.\scripts\run-local.ps1 -Mode run-gateway로컬에서 Telegram 없이 전체 플로우를 검증하는 핵심 구성입니다.
./scripts/run-local.sh up관리 명령:
./scripts/run-local.sh start
./scripts/run-local.sh stop
./scripts/run-local.sh restart
./scripts/run-local.sh status
./scripts/run-local.sh logs
./scripts/run-local.sh doctor기본 URL:
- UI:
http://127.0.0.1:9082/_mock/ui?token=mock_token_1&chat_id=1001&user_id=9001 - Bot health:
http://127.0.0.1:8600/healthz
./scripts/run-local-multibot.sh start기본 동작:
- 기본 config:
config/bots.multibot.yaml - 기본
MAX_BOTS=0(0이면 전체 봇 사용) - mock + supervisor 동시 기동
- 실행 시
RUNTIME_DIR/bots.effective.yaml을 생성 - bot별
database_url이 비어 있으면 런타임용 SQLite 파일을 자동 주입해 물리적 DB 격리를 보장
유용한 명령:
./scripts/run-local-multibot.sh status
./scripts/run-local-multibot.sh logs
./scripts/run-local-multibot.sh stop
MAX_BOTS=3 ./scripts/run-local-multibot.sh start
CONFIG_PATH=config/bots.yaml ./scripts/run-local-multibot.sh start.\scripts\run-mock-messenger.ps1
.\scripts\run-local-with-mock.ps1 -Config config/bots.yaml
.\scripts\run-mock-codex-bridge.ps1
.\scripts\stop-mock-codex-bridge.ps1- Session 패널은
Session 기본 / Webhook / Rate Limit3개 아코디언으로 분리되며, 각 섹션 접힘 상태는 localStorage에 저장됩니다. Project / Skill / Role제어는 봇 카드가 아니라 Session 기본 섹션으로 이동했습니다.- Project 셀렉터의 후보는
GET /_mock/projects로 로드되며, 기준은 다음과 같습니다.- 현재 workspace 루트는 항상 포함
- workspace의 1-depth 하위 디렉터리 중
.git,package.json,pyproject.toml,requirements.txt,go.mod,Cargo.toml,README.md같은 marker 파일이 있는 디렉터리만 포함
- Session Project 적용 우선순위:
- 1순위: diagnostics의
session.current_project(실제 런타임 상태) - 2순위: 프로필의
selected_project(UI 저장값)
- 1순위: diagnostics의
- 좌측 사이드바 패널(
Parallel Results / Debate Panel / Cowork Panel / Control Tower)은 모두 동일한 collapse 토글 패턴과 상태 저장(localStorage)을 사용합니다. - 패널을 모두 펼친 경우, 개별 패널만이 아니라 사이드바 전체(
.bot-sidebar)에서 스크롤되도록 동작합니다.
- 아래 명령은 Telegram 백엔드 slash command가 아니라 Mock Dashboard UI 오케스트레이션 명령입니다.
- 입력 위치는
message-input또는병렬 전송 메시지(parallel-message-input) 둘 다 가능합니다. - 공통 옵션:
--rounds <n>: 기본값은 명령별 상이, 범위1~8--max-turn-sec <n>: 턴 타임아웃, 범위10~240--keep-session:/new없이 현재 세션을 유지하고 실행
| Command | 기본 rounds | 최소 봇 | 설명 |
|---|---|---|---|
/talk <문장> |
2 | 2 | 자유 대화 라운드 |
/relay <주제> |
3 | 2 | 릴레이 대사 이어쓰기 |
/pitchbattle <주제> |
2 | 2 | 아이디어 피치 배틀 + 판정 |
/quizbattle <주제> |
2 | 2 | 퀴즈 배틀 + 판정 |
/debate-lite <주제> |
2 | 2 | 경량 토론 + 판정 |
/improv <상황> |
3 | 2 | 즉흥극 릴레이 |
/quest <미션> |
3 | 2 | 협동 퀘스트 + 성공/실패 판정 |
/memechain <주제> |
3 | 2 | 한 줄 밈 체인 |
/court <사건> |
2 | 3 | 법정극 + 판결 |
- 결과는
Parallel Results와 상단Talk / Play Viewer에 함께 기록됩니다.
| Command | Description |
|---|---|
/start |
웰컴/사용 가이드 메시지 |
/help |
명령어 요약 |
/new |
새 세션 생성 |
/status |
현재 bot/adapter/model/session/thread/summary 상태 |
/reset |
현재 세션 리셋 후 새 세션 |
/summary |
rolling summary 출력 |
/mode |
현재 provider 확인 + 사용법 안내 |
/mode <codex|gemini|claude> |
provider 전환 (활성 run 중이면 차단) |
/model |
현재 provider의 model/허용 목록 조회 |
/model <name> |
현재 provider model 변경 (활성 run 중이면 차단) |
/project |
현재 세션 project root 조회 + 사용법 안내 |
/project <directory-path> |
세션 작업 경로 변경 (off/default/reset으로 해제, 활성 run 중이면 차단) |
/skills |
로컬 설치된 skill 프로필 목록 조회 |
/skill |
현재 세션 skill 조회 + 사용법 안내 |
/skill <skill-id[,skill-id...]> |
현재 세션 skill 적용 (활성 run 중이면 차단) |
/skill off |
현재 세션 skill 해제 |
/unsafe on [minutes] / /unsafe off |
세션 unsafe 모드 on/off (1~120분, 활성 run 중이면 차단) |
/providers |
provider binary 설치여부 + 기본 model 표시 |
/stop |
활성 run 취소 요청 |
/youtube <query> / /yt <query> |
YouTube 검색 후 watch URL 전송 |
/echo <text> |
입력 텍스트 그대로 에코 |
일반 텍스트를 보내면 run queue에 turn이 적재됩니다.
다음 명령은 Mock Dashboard UI 클라이언트(/_mock/ui)가 직접 해석해서 멀티봇 실행을 오케스트레이션합니다.
백엔드 Telegram Command Handler의 slash command 라우팅과는 별개입니다.
| Command | Description |
|---|---|
/talk <문장> [--rounds n] [--max-turn-sec n] [--keep-session] |
자유 대화 라운드 실행 |
/relay <주제> [--rounds n] [--max-turn-sec n] [--keep-session] |
릴레이 대화 |
/pitchbattle <주제> [--rounds n] [--max-turn-sec n] [--keep-session] |
피치 배틀 + 판정 |
/quizbattle <주제> [--rounds n] [--max-turn-sec n] [--keep-session] |
퀴즈 배틀 + 판정 |
/debate-lite <주제> [--rounds n] [--max-turn-sec n] [--keep-session] |
경량 토론 + 판정 |
/improv <상황> [--rounds n] [--max-turn-sec n] [--keep-session] |
즉흥극 |
/quest <미션> [--rounds n] [--max-turn-sec n] [--keep-session] |
협동 퀘스트 + 성공/실패 판정 |
/memechain <주제> [--rounds n] [--max-turn-sec n] [--keep-session] |
밈 체인 |
/court <사건> [--rounds n] [--max-turn-sec n] [--keep-session] |
법정극 + 판결 (3 bots 이상 필요) |
/cowork <요청> [--project-id id] [--max-parallel n] [--max-turn-sec n] [--keep-session] [--strict] |
역할 기반 협업 실행 및 아티팩트 생성 |
추가 동작:
- 인라인 callback 버튼(
요약,다시생성,다음추천,중단) - action token TTL 기본 24시간
- YouTube 자연어 의도(한/영, 오타 변형 일부) 처리
Skill 관리:
- 외부 스킬은 프로젝트 루트
skills/<skill-id>/SKILL.md구조로 관리 remotion-dev/skills동기화:./scripts/sync-remotion-skill.sh- 런타임은 세션의
active_skill을 읽어 실행 프롬프트 preamble에 자동 주입
| Method | Path | Description |
|---|---|---|
GET |
/healthz |
liveness |
GET |
/readyz |
readiness |
GET |
/metrics |
runtime + queue counters |
GET |
/audit_logs |
embedded bot 최근 audit 로그 조회 |
POST |
/telegram/webhook/{bot_id}/{path_secret} |
Telegram webhook ingest |
| Method | Path |
|---|---|
POST |
/bot{token}/getUpdates |
POST |
/bot{token}/setWebhook |
POST |
/bot{token}/deleteWebhook |
POST |
/bot{token}/sendMessage |
POST |
/bot{token}/editMessageText |
POST |
/bot{token}/answerCallbackQuery |
POST |
/bot{token}/sendDocument |
POST |
/bot{token}/sendPhoto |
| Method | Path | Description |
|---|---|---|
GET |
/_mock/ui |
웹 UI |
GET |
/_mock/threads |
스레드 목록 |
POST |
/_mock/send |
유저 메시지 주입 |
GET |
/_mock/messages |
메시지 타임라인 조회 |
POST |
/_mock/messages/clear |
타임라인/업데이트 정리 |
GET |
/_mock/document/{document_id} |
문서/이미지 다운로드 |
GET |
/_mock/state |
mock 내부 상태 |
GET |
/_mock/bot_catalog |
봇 카탈로그 |
GET |
/_mock/runtime_profile |
multi-bot runtime 프로파일(effective/source/max_bots) |
GET |
/_mock/projects |
Session Project 선택 후보 목록 |
GET |
/_mock/skills |
설치된 skill 카탈로그 |
GET |
/_mock/routing/suggest |
라우팅 정책 기반 provider/model 제안 |
POST |
/_mock/bot_catalog/add |
동적 bot 추가 |
POST |
/_mock/bot_catalog/delete |
bot 삭제 |
POST |
/_mock/bot_catalog/role |
bot 기본 역할(controller/planner/executor/integrator) 저장 |
GET |
/_mock/bot_diagnostics |
bot 진단(health/metrics/session/error_tag) |
GET |
/_mock/audit_logs |
최근 audit 로그 조회 |
GET |
/_mock/control_tower |
전체 bot 상태 집계(SLO/state/action) |
POST |
/_mock/control_tower/recover |
/stop 또는 /stop+/new 기반 자동 복구 |
GET |
/_mock/forensics/bundle |
diagnostics/audit/messages/updates 포렌식 번들 |
POST |
/_mock/debate/start |
멀티봇 토론 시작 |
GET |
/_mock/debate/active |
진행 중 토론 조회 |
GET |
/_mock/debate/{debate_id} |
토론 상세/턴 로그 조회 |
POST |
/_mock/debate/{debate_id}/stop |
토론 중단 요청 |
POST |
/_mock/cowork/start |
역할 기반 협업(/cowork) 시작 |
GET |
/_mock/cowork/active |
진행 중 협업 조회 |
GET |
/_mock/cowork/{cowork_id} |
협업 단계/작업/리포트 조회 |
POST |
/_mock/cowork/{cowork_id}/stop |
협업 중단 요청(reason, source, requested_by optional body 지원) |
GET |
/_mock/cowork/{cowork_id}/artifacts |
협업 아티팩트 메타 조회 |
GET |
/_mock/cowork/{cowork_id}/artifact/{filename} |
협업 아티팩트 파일 다운로드 |
POST |
/_mock/rate_limit |
429 시뮬레이션 룰 |
botstelegram_updatestelegram_update_jobssessionsturnscli_run_jobscli_eventssession_summariesaction_tokensdeferred_button_actionsruntime_metric_countersaudit_logs
telegram_update_jobs:queued,leased,completed,failedcli_run_jobs:queued,leased,in_flight,completed,failed,cancelledturns:queued,in_flight,completed,failed,cancelledsessions:active,reset
- 활성 run 유니크 인덱스:
uq_cli_run_jobs_bot_chat_active - 활성 session 유니크 인덱스:
uq_sessions_bot_chat_active - 이벤트 순서 유니크:
(turn_id, seq)incli_events - DB schema + SQL migrations는 런타임 시작 시 자동 적용
GET /metrics 응답 구조:
telegram_update_jobscli_run_jobsin_flight_runstelegram_updates_totaltelegram_update_jobs_by_statuscli_run_jobs_by_statusruntime_counters
주의:
/metrics는 Prometheus text 포맷이 아니라 JSON 응답입니다.- Mock UI의
/_mock/bot_diagnostics,/_mock/control_tower는 이 JSON을 가공해서 표시합니다.
runtime_counters 대표 키:
webhook_accept_totalwebhook_duplicate_updatewebhook_reject_*callback_ack_successcallback_ack_failedtelegram_rate_limit_retry_totaltelegram_rate_limit_retry.<method>worker_heartbeat.run_workerworker_heartbeat.update_workerprovider_switch_total.<provider>provider_run_failed.<provider>provider_run_watchdog_timeout.<provider>
pytest주요 커버리지:
- settings/token fallback 로직
- adapter 명령 생성 + 이벤트 정규화
- telegram API parsing/poller
- command 핸들러(owner check, mode 전환, callback action token)
- run worker artifact 전달(image/html)
- queue/repository 동시성 유틸
- mock messenger API/webhook/polling/diagnostics
- supervisor 프로세스 스펙 계산
./scripts/verify-mock-ui-e2e.sh검증 포인트:
- 멀티봇 사이드바/레이아웃
- slash command suggestion
- 병렬 전송 결과 수집
- profile 추가/삭제 흐름
실제 라이브 UI로 /cowork 10개 웹 케이스를 다시 실행하고 result/에 증빙까지 남기려면:
./scripts/run-cowork-web-10cases.sh --headed옵션 예시:
./scripts/run-cowork-web-10cases.sh --headless --max-turn-sec 45 --case-timeout-sec 240
./scripts/run-cowork-web-10cases.sh --headless --case-timeout-sec 120
./scripts/run-cowork-web-10cases.sh --headless --case-timeout-sec 120 --allow-unsafe-timeout결과 위치:
result/cowork_web_test_10cases_live_<timestamp>/report.mdresult/cowork_web_test_10cases_live_<timestamp>/report.json- 케이스별
request.json,snapshot.json,artifacts.json,status.log,summary.md - 케이스별
ui/cowork-panel.png,ui/project-page.png,ui/failure-panel.png - 케이스별
cowork_artifacts/전체 복사본
실패 시 우선 확인:
- 루트
runner.log - 케이스
status.log - 실패 케이스
playwright/trace.zip cowork_artifacts/final/controller_final_report.md
timeout 분류 규칙:
runner_case_timeout: live UI runner가 case budget 초과로/_mock/cowork/{id}/stop을 요청한 경우turn_timeout: 특정 participant bot의 turn timeoutstage_timeout_budget: runner 요청 timeout이 cowork 계산 budget보다 작아서 자동 상향된 경우
live rerun 스크립트의 timeout 보정 규칙:
- 기본적으로
--case-timeout-sec가 cowork snapshot의budget_floor_sec보다 작으면 자동으로 상향됩니다. - 상향된 값은
report.json,summary.md,status.log,suite_meta.json에 모두 기록됩니다. - 강제로 unsafe timeout을 유지하고 싶으면
--allow-unsafe-timeout을 명시해야 합니다.
./scripts/verify-multibot-smoke.sh
./scripts/verify-release-flow.sh| Script | Purpose |
|---|---|
scripts/bootstrap-local.ps1 |
Windows bootstrap(venv + deps + config seed) |
scripts/run-local.ps1 |
Windows runtime helper(supervisor/run-bot/run-gateway) |
scripts/run-local.sh |
macOS/Linux single-bot stack wrapper |
scripts/run-local-fixed.sh |
single-bot stack 실제 실행기(mock + bot) |
scripts/run-local-multibot.sh |
multi-bot stack 실행기(mock + supervisor) |
scripts/run-cowork-web-10cases.sh |
temp runtime + real browser로 /cowork 웹 10케이스 재실행 및 증빙 리포트 생성, unsafe case timeout 자동 상향 지원 |
scripts/run-local-with-mock.ps1 |
Windows에서 mock + supervisor 동시 실행 |
scripts/run-mock-messenger.ps1 |
Windows mock만 실행 |
scripts/run-mock-codex-bridge.ps1 |
mock + codex bridge 실행 |
scripts/stop-mock-codex-bridge.ps1 |
bridge/mock 정리 |
scripts/report_cowork_web_suite.py |
live cowork raw evidence를 report.md/report.json으로 집계하고 timeout origin/actor/budget metadata를 노출 |
scripts/verify-multibot-smoke.sh |
멀티봇 스모크 검증 |
scripts/verify-mock-ui-e2e.sh |
mock UI Playwright E2E |
scripts/verify-release-flow.sh |
주요 테스트 + 런타임 스모크 |
codex,gemini,claudeCLI 설치 확인/providers로 설치 상태 확인- 설치된 provider로
/mode <codex|gemini|claude>전환 - 필요하면
CODEX_BIN,GEMINI_BIN,CLAUDE_BIN으로 바이너리 경로를 직접 지정 codex는 VS Code / ChatGPT extension 번들 바이너리 자동 탐색 fallback도 지원
- 메시지:
A run is already active... /stop실행 후 재시도- active run 보호 인덱스가 의도적으로 중복 실행을 차단
- 기본 turn watchdog은
RUN_TURN_TIMEOUT_SEC=90초이며, 초과 시 run은error로 종료됩니다. - watchdog timeout이 감지되면
runtime_counters.provider_run_watchdog_timeout.<provider>가 증가합니다. GET /metrics,/_mock/bot_diagnostics,/_mock/control_tower에서 timeout 흔적(in_flight, run_status, error_tag)을 먼저 확인하세요.- timeout이 반복되면
RUN_TURN_TIMEOUT_SEC상향, 모델 변경(/model), 세션 재생성(/new) 순으로 점검하세요.
- 협업 단계에서 participant별 실행은 같은
(bot_id, chat_id)조합에 대해 직렬화되어 동작합니다(중복 active run 충돌 완화). - 그래도 기존 활성 run이 남아 있으면
/stop선행이 필요합니다. - live rerun 스크립트는 기본적으로 temp config/runtime/port를 사용하므로 기존
9082스택과 분리됩니다. --project-id를 주면 결과 아티팩트 루트가 고정되어 케이스별 비교가 쉬워집니다.- 웹 profile(
landing-basic,form-validation,seo-landing등)은 기본적으로web guaranteed mode로 동작하며, deterministic scaffold + audit가 통과하면 planner/implementer/qa/controller LLM turn 없이도completed가 가능합니다. - 최종 품질 게이트에서 아래 조건이면
failed처리됩니다.- 실행 태스크 실패/중단 존재
- 렌더링/화면 요청인데 실행 가능한 링크 부재
- 최종 결론이
미이행/미완료등 실패 신호 포함
Cowork Panel의budget,stop_reason,last_timeout_event와/_mock/cowork/{cowork_id}/artifacts를 함께 확인하세요.- timeout 책임 해석 규칙:
timeout_origin=runner_case_timeout: 원인자는 live runner이며, bot fault가 아닙니다.timeout_origin=turn_timeout:timeout_actor_label,timeout_actor_role,timeout_stage_type에 기록된 participant가 직접 원인자입니다.timeout_origin=stage_timeout_budget: runner timeout 계약이 잘못된 경우이며,budget_floor_sec와applied_case_timeout_sec를 먼저 확인해야 합니다.
- 최소 선택 봇 수 조건을 먼저 확인하세요. 특히
/court는 3개 이상 봇이 필요합니다. - 옵션 오탈자(
--foo등)는 즉시 파싱 실패 처리됩니다. - 활성 run 충돌이 있으면
/stop후 재시도하거나--keep-session없이 실행해 세션을 재정비하세요. - 응답이 느리면
--rounds를 낮추고--max-turn-sec를 조정해 전체 대기 시간을 줄일 수 있습니다. - 판정 명령에서 형식(
WINNER/VERDICT/RESULT)이 없으면 Viewer에[판정 실패]가 표시됩니다(실행 자체는 완료 처리).
- 목록 자체는
/_mock/projects결과(workspace + marker가 있는 1-depth 하위 프로젝트)에서 구성됩니다. - UI 선택값 표시 우선순위는
session.current_project(런타임) >selected_project(UI 저장값)입니다. - 실제 적용은
/project <path>명령으로 처리되며, 활성 run이 있으면 적용이 차단됩니다.
- webhook 모드에서는
getUpdates가 기본 차단됨 - 필요 시 mock 실행 시
--allow-get-updates-with-webhook사용 - 또는 polling 모드로 전환
MAX_BOTS=0이면 전체 봇을 사용하고,MAX_BOTS>0이면 앞에서부터 N개만 사용합니다.- 실제 런타임은 원본 config가 아니라
bots.effective.yaml을 기준으로 동작할 수 있습니다. /_mock/runtime_profile응답이나status출력에서 effective/source bot 수를 먼저 확인하세요.
- single-bot 기본:
9082(mock),8600(bot) - multi-bot 기본:
9082(mock),8600+(embedded bots),4312(gateway) status/doctor명령으로 상태 확인
- 로컬 mock base URL(
127.0.0.1/localhost)일 때는 ingest state reset 로직이 동작해 offset 문제를 줄입니다.
This project is licensed under the MIT License. See LICENSE.
- Entrypoint:
src/telegram_bot_new/main.py - Supervisor:
src/telegram_bot_new/supervisor.py - Embedded runtime:
src/telegram_bot_new/runtime_embedded.py - Gateway runtime:
src/telegram_bot_new/runtime_gateway.py - Workers:
src/telegram_bot_new/workers/ - Adapters:
src/telegram_bot_new/adapters/ - Repository/DB:
src/telegram_bot_new/db/ - Mock messenger:
src/telegram_bot_new/mock_messenger/ - Tests:
tests/