diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 00000000..2e8b3ce6 --- /dev/null +++ b/README-EN.md @@ -0,0 +1,83 @@ +# GitHub Sentinel + +

+
English | 中文 +

+ +GitHub Sentinel is an open-source tool AI Agent designed for developers and project managers. It automatically retrieves and aggregates updates from subscribed GitHub repositories on a regular basis (daily/weekly). Key features include subscription management, update retrieval, notification system, and report generation. + +## Features +- Subscription management +- Update retrieval +- Notification system +- Report generation + +## Getting Started + +### 1. Install Dependencies + +First, install the required dependencies: + +```sh +pip install -r requirements.txt +``` + +### 2. Configure the Application + +Edit the `config.json` file to set up your GitHub token, notification settings, subscription file, and update interval: + +```json +{ + "github_token": "your_github_token", + "notification_settings": { + "email": "your_email@example.com", + "slack_webhook_url": "your_slack_webhook_url" + }, + "subscriptions_file": "subscriptions.json", + "update_interval": 86400 +} +``` + +### 3. How to Run + +GitHub Sentinel supports three different ways to run the application: + +#### A. Run as a Command-Line Tool + +You can run the application interactively from the command line: + +```sh +python src/command_tool.py +``` + +In this mode, you can manually input commands to manage subscriptions, retrieve updates, and generate reports. + +#### B. Run as a Daemon Process with Scheduler + +To run the application as a background service (daemon) that regularly checks for updates: + +1. Ensure you have the `python-daemon` package installed: + + ```sh + pip install python-daemon + ``` + +2. Launch the daemon process: + + ```sh + nohup python3 src/daemon_process.py > logs/daemon_process.log 2>&1 & + ``` + + - This will start the scheduler in the background, checking for updates at the interval specified in your `config.json`. + - Logs will be saved to the `logs/daemon_process.log` file. + +#### C. Run as a Gradio Server + +To run the application with a Gradio interface, allowing users to interact with the tool via a web interface: + +```sh +python src/gradio_server.py +``` + +- This will start a web server on your machine, allowing you to manage subscriptions and generate reports through a user-friendly interface. +- By default, the Gradio server will be accessible at `http://localhost:7860`, but you can share it publicly if needed. diff --git a/README.md b/README.md index 62a5cc04..351f95c5 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,31 @@ # GitHub Sentinel -GitHub Sentinel is an open-source tool AI Agent designed for developers and project managers. It automatically retrieves and aggregates updates from subscribed GitHub repositories on a regular basis (daily/weekly). Key features include subscription management, update retrieval, notification system, and report generation. +

+
English | 中文 +

-## Features -- Subscription management -- Update retrieval -- Notification system -- Report generation +GitHub Sentinel 是一个开源的工具 AI 代理,专为开发人员和项目经理设计。它会定期(每日/每周)自动从订阅的 GitHub 仓库中检索和汇总更新。主要功能包括订阅管理、更新检索、通知系统和报告生成。 -## Getting Started -1. Install dependencies: - ```sh - pip install -r requirements.txt - ``` +## 功能 +- 订阅管理 +- 更新检索 +- 通知系统 +- 报告生成 -2. Configure the application by editing `config.json`. +## 快速开始 -3. Run the application: - ```sh - python src/main.py - ``` +### 1. 安装依赖 + +首先,安装所需的依赖项: + +```sh +pip install -r requirements.txt +``` + +### 2. 配置应用 + +编辑 `config.json` 文件,以设置您的 GitHub 令牌、通知设置、订阅文件和更新间隔: -## Configuration -The configuration file `config.json` should contain the following settings: ```json { "github_token": "your_github_token", @@ -34,3 +37,47 @@ The configuration file `config.json` should contain the following settings: "update_interval": 86400 } ``` + +### 3. 如何运行 + +GitHub Sentinel 支持以下三种运行方式: + +#### A. 作为命令行工具运行 + +您可以从命令行交互式地运行该应用: + +```sh +python src/command_tool.py +``` + +在此模式下,您可以手动输入命令来管理订阅、检索更新和生成报告。 + +#### B. 作为后台进程运行(带调度器) + +要将该应用作为后台服务(守护进程)运行,它将定期检查更新: + +1. 确保您已安装 `python-daemon` 包: + + ```sh + pip install python-daemon + ``` + +2. 启动后台进程: + + ```sh + nohup python3 src/daemon_process.py > logs/daemon_process.log 2>&1 & + ``` + + - 这将启动后台调度器,按照 `config.json` 中指定的间隔定期检查更新。 + - 日志将保存到 `logs/daemon_process.log` 文件中。 + +#### C. 作为 Gradio 服务器运行 + +要使用 Gradio 界面运行应用,允许用户通过 Web 界面与该工具交互: + +```sh +python src/gradio_server.py +``` + +- 这将在您的机器上启动一个 Web 服务器,允许您通过用户友好的界面管理订阅和生成报告。 +- 默认情况下,Gradio 服务器将可在 `http://localhost:7860` 访问,但如果需要,您可以公开共享它。 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c428aa53..ddee22e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ requests openai gradio -logoru \ No newline at end of file +loguru +python-daemon \ No newline at end of file diff --git a/src/command_tool.py b/src/command_tool.py new file mode 100644 index 00000000..3a41a0f0 --- /dev/null +++ b/src/command_tool.py @@ -0,0 +1,40 @@ +import shlex + +from config import Config +from github_client import GitHubClient +from notifier import Notifier +from report_generator import ReportGenerator +from llm import LLM +from subscription_manager import SubscriptionManager +from command_handler import CommandHandler +from logger import LOG + +def main(): + config = Config() + github_client = GitHubClient(config.github_token) + notifier = Notifier(config.notification_settings) + llm = LLM() + report_generator = ReportGenerator(llm) + subscription_manager = SubscriptionManager(config.subscriptions_file) + command_handler = CommandHandler(github_client, subscription_manager, report_generator) + + parser = command_handler.parser + command_handler.print_help() + + while True: + try: + user_input = input("GitHub Sentinel> ") + if user_input in ['exit', 'quit']: + break + try: + args = parser.parse_args(shlex.split(user_input)) + if args.command is None: + continue + args.func(args) + except SystemExit as e: + LOG.error("Invalid command. Type 'help' to see the list of available commands.") + except Exception as e: + LOG.error(f"Unexpected error: {e}") + +if __name__ == '__main__': + main() diff --git a/src/daemon_process.py b/src/daemon_process.py new file mode 100644 index 00000000..d084a925 --- /dev/null +++ b/src/daemon_process.py @@ -0,0 +1,51 @@ +import daemon +import threading +import time + + +from config import Config +from github_client import GitHubClient +from notifier import Notifier +from report_generator import ReportGenerator +from llm import LLM +from subscription_manager import SubscriptionManager +from scheduler import Scheduler +from logger import LOG + +def run_scheduler(scheduler): + scheduler.start() + +def main(): + config = Config() + github_client = GitHubClient(config.github_token) + notifier = Notifier(config.notification_settings) + llm = LLM() + report_generator = ReportGenerator(llm) + subscription_manager = SubscriptionManager(config.subscriptions_file) + + scheduler = Scheduler( + github_client=github_client, + notifier=notifier, + report_generator=report_generator, + subscription_manager=subscription_manager, + interval=config.update_interval + ) + + scheduler_thread = threading.Thread(target=run_scheduler, args=(scheduler,)) + scheduler_thread.daemon = True + scheduler_thread.start() + + LOG.info("Scheduler thread started.") + + # Use python-daemon to properly daemonize the process + with daemon.DaemonContext(): + try: + while True: + time.sleep(config.update_interval) + except KeyboardInterrupt: + LOG.info("Daemon process stopped.") + +if __name__ == '__main__': + main() + +# nohup python3 src/daemon_process.py > logs/daemon_process.log 2>&1 & diff --git a/src/gradio_server.py b/src/gradio_server.py new file mode 100644 index 00000000..ca8f5812 --- /dev/null +++ b/src/gradio_server.py @@ -0,0 +1,38 @@ +import gradio as gr + +from config import Config +from github_client import GitHubClient +from report_generator import ReportGenerator +from llm import LLM +from subscription_manager import SubscriptionManager +from logger import LOG + +config = Config() +github_client = GitHubClient(config.github_token) +llm = LLM() +report_generator = ReportGenerator(llm) +subscription_manager = SubscriptionManager(config.subscriptions_file) + + +def export_progress_by_date_range(repo, days): + raw_file_path = github_client.export_progress_by_date_range(repo, days) + report, report_file_path = report_generator.generate_report_by_date_range(raw_file_path, days) + + return report, report_file_path + +demo = gr.Interface( + fn=export_progress_by_date_range, + title="GitHubSentinel", + inputs=[ + gr.Dropdown( + subscription_manager.list_subscriptions(), label="订阅列表", info="已订阅GitHub项目" + ), + gr.Slider(value=2, minimum=1, maximum=7, step=1, label="报告周期", info="生成项目过去一段时间进展,单位:天"), + + ], + outputs=[gr.Markdown(), gr.File(label="下载报告")], +) + +if __name__ == "__main__": + demo.launch(share=True, server_name="0.0.0.0") + # demo.launch(share=True, server_name="0.0.0.0", auth=("django", "1234")) \ No newline at end of file diff --git a/src/report_generator.py b/src/report_generator.py index a7734c8a..37aa7bdc 100644 --- a/src/report_generator.py +++ b/src/report_generator.py @@ -59,7 +59,11 @@ def generate_daily_report(self, markdown_file_path): with open(report_file_path, 'w+') as report_file: report_file.write(report) # 写入生成的报告 + LOG.info(f"Generated report saved to {report_file_path}") # 记录生成报告日志 + + return report, report_file_path + def generate_report_by_date_range(self, markdown_file_path, days): # 生成特定日期范围的报告,流程与日报生成类似 @@ -72,4 +76,8 @@ def generate_report_by_date_range(self, markdown_file_path, days): with open(report_file_path, 'w+') as report_file: report_file.write(report) + LOG.info(f"Generated report saved to {report_file_path}") # 记录生成报告日志 + + return report, report_file_path +