From c4632d32be60142b7ef1a9178bc362844cf159c3 Mon Sep 17 00:00:00 2001 From: shaojie <741047428@qq.com> Date: Mon, 18 Aug 2025 11:28:03 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E4=BC=98=E5=8C=96=20(backend/config/config.g?= =?UTF-8?q?o)=20=E8=A7=A3=E5=86=B3=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9A=20?= =?UTF-8?q?=E2=9D=8C=20=E6=9C=AC=E5=9C=B0=E5=BC=80=E5=8F=91=E6=97=B6?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E6=89=8B=E5=8A=A8=E8=AE=BE=E7=BD=AE=E5=A4=A7?= =?UTF-8?q?=E9=87=8F=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=EF=BC=8C=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E4=BD=93=E9=AA=8C=E5=B7=AE=20=E2=9D=8C=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=BC=BA=E4=B9=8F=E9=BB=98=E8=AE=A4=E5=80=BC=EF=BC=8C?= =?UTF-8?q?=E6=97=A0=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=97=B6=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E5=8F=AF=E8=83=BD=E5=90=AF=E5=8A=A8=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=20=E2=9D=8C=20=E6=9C=BA=E5=99=A8ID=E6=96=87=E4=BB=B6=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E7=A1=AC=E7=BC=96=E7=A0=81=EF=BC=8C=E4=B8=8D=E5=A4=9F?= =?UTF-8?q?=E7=81=B5=E6=B4=BB=20=E4=BC=98=E5=8C=96=E6=96=B9=E6=A1=88?= =?UTF-8?q?=EF=BC=9A=20=E2=9C=85=20=E6=94=AF=E6=8C=81=20config.local.yaml?= =?UTF-8?q?=20=E6=9C=AC=E5=9C=B0=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E7=AE=80=E5=8C=96=E5=BC=80=E5=8F=91=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=20=E2=9C=85=20=E5=BB=BA=E7=AB=8B=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=BC=98=E5=85=88=E7=BA=A7=EF=BC=9A=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F=20>=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=20>=20=E9=BB=98=E8=AE=A4=E5=80=BC=20=E2=9C=85=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AE=8C=E6=95=B4=E7=9A=84=E9=BB=98=E8=AE=A4=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E7=A1=AE=E4=BF=9D=E9=9B=B6=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=20=E2=9C=85=20=E6=96=B0=E5=A2=9E=20machine?= =?UTF-8?q?=5Fid=5Ffile=20=E9=85=8D=E7=BD=AE=E9=A1=B9=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=B7=AF=E5=BE=84=202.=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=B8=8A=E6=8A=A5=E6=9C=BA=E5=88=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20(backend/pkg/report/report.go)=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9A=20=E2=9D=8C=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E4=B8=8A=E6=8A=A5=E5=92=8C=E6=9C=BA=E5=99=A8ID?= =?UTF-8?q?=E7=94=9F=E6=88=90=E8=80=A6=E5=90=88=EF=BC=8C=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E6=8E=A7=E5=88=B6=20=E2=9D=8C=20=E6=9C=BA?= =?UTF-8?q?=E5=99=A8ID=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E7=A1=AC?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E4=B8=BA=20/app/static/.machine=5Fid=20?= =?UTF-8?q?=E2=9D=8C=20=E6=B2=A1=E6=9C=89=E4=B8=8A=E6=8A=A5=E5=AF=86?= =?UTF-8?q?=E9=92=A5=E6=97=B6=E7=A8=8B=E5=BA=8F=E8=A1=8C=E4=B8=BA=E4=B8=8D?= =?UTF-8?q?=E5=A4=9F=E4=BC=98=E9=9B=85=20=E4=BC=98=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E6=A1=88=EF=BC=9A=20=E2=9C=85=20=E5=88=86=E7=A6=BB=E6=9C=BA?= =?UTF-8?q?=E5=99=A8ID=E7=94=9F=E6=88=90=E5=92=8C=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=B8=8A=E6=8A=A5=E9=80=BB=E8=BE=91=20=E2=9C=85=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=85=8D=E7=BD=AE=E5=8C=96=E7=9A=84=E6=9C=BA=E5=99=A8?= =?UTF-8?q?ID=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=20=E2=9C=85=20=E4=BC=98?= =?UTF-8?q?=E9=9B=85=E9=99=8D=E7=BA=A7=EF=BC=9A=E6=97=A0=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E5=AF=86=E9=92=A5=E6=97=B6=E8=B7=B3=E8=BF=87=E4=B8=8A=E6=8A=A5?= =?UTF-8?q?=E4=BD=86=E4=BF=9D=E7=95=99=E6=9C=BA=E5=99=A8ID=E7=94=9F?= =?UTF-8?q?=E6=88=90=20=E2=9C=85=20=E4=BB=A3=E7=A0=81=E9=87=8D=E6=9E=84?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E5=8F=96=20ensureMachineID()=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E6=8F=90=E9=AB=98=E5=8F=AF=E7=BB=B4=E6=8A=A4?= =?UTF-8?q?=E6=80=A7=203.=20=E9=A1=B9=E7=9B=AE=E7=AE=A1=E7=90=86=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E5=8C=96=20(.gitignore)=20=E8=A7=A3=E5=86=B3=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=9A=20=E2=9D=8C=20=E7=BC=BA=E4=B9=8F?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E7=9A=84=E5=BF=BD=E7=95=A5=E8=A7=84=E5=88=99?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E8=83=BD=E8=AF=AF=E6=8F=90=E4=BA=A4=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=20=E2=9D=8C=20=E4=B8=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=B8=BB=E6=B5=81IDE=E7=9A=84=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E8=A7=84=E5=88=99=20=E4=BC=98=E5=8C=96=E6=96=B9=E6=A1=88?= =?UTF-8?q?=EF=BC=9A=20=E2=9C=85=20=E6=B7=BB=E5=8A=A0=20IDE=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=88IntelliJ=20IDEA=E3=80=81VS=20Code=EF=BC=89=20?= =?UTF-8?q?=E2=9C=85=20=E5=BF=BD=E7=95=A5=E7=B3=BB=E7=BB=9F=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=EF=BC=88.DS=5FStore=20=E7=AD=89?= =?UTF-8?q?=EF=BC=89=20=E2=9C=85=20=E5=BF=BD=E7=95=A5=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=92=8C=E8=BF=90=E8=A1=8C=E6=97=B6=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?=E2=9C=85=20=E8=A7=84=E8=8C=83=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 40 +++++++++++++++++++++ backend/config/config.go | 18 +++++++++- backend/config/config.local.yaml | 62 ++++++++++++++++++++++++++++++++ backend/pkg/report/report.go | 40 +++++++++++++++++---- 4 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 backend/config/config.local.yaml diff --git a/.gitignore b/.gitignore index dd630cfb..46203571 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,43 @@ backend/assets backend/docs/swagger.json backend/assets-amd64 + +# 本地开发配置文件,不提交到代码库 +#backend/config/config.local.yaml + +# IDE - IntelliJ IDEA +.idea/ +*.iml +*.ipr +*.iws +out/ + +# IDE - VS Code +.vscode/ +*.code-workspace + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Temporary folders +tmp/ +temp/ diff --git a/backend/config/config.go b/backend/config/config.go index d11a9dfb..f80615bc 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -80,7 +80,8 @@ type Config struct { } `mapstructure:"extension"` DataReport struct { - Key string `mapstructure:"key"` + Key string `mapstructure:"key"` + MachineIDFile string `mapstructure:"machine_id_file"` } `mapstructure:"data_report"` Security struct { @@ -121,6 +122,20 @@ func Init() (*Config, error) { v.SetEnvPrefix("MONKEYCODE") v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + // 可选的配置文件读取(保持向后兼容) + // 优先级:环境变量 > 配置文件 > 默认值 + v.SetConfigType("yaml") + v.AddConfigPath("./config") + v.AddConfigPath(".") + + // 尝试读取本地开发配置(仅用于开发环境便利性) + v.SetConfigName("config.local") + if err := v.ReadInConfig(); err != nil { + // 本地配置不存在是正常的,不需要报错 + // 线上部署完全依赖环境变量,这样保持向后兼容 + } + + // 设置默认值,确保在没有配置文件时程序能启动(云上部署场景) v.SetDefault("debug", false) v.SetDefault("read_only", false) v.SetDefault("logger.level", "info") @@ -152,6 +167,7 @@ func Init() (*Config, error) { v.SetDefault("extension.limit", 1) v.SetDefault("extension.limit_second", 10) v.SetDefault("data_report.key", "") + v.SetDefault("data_report.machine_id_file", "static/.machine_id") v.SetDefault("security.queue_limit", 5) v.SetDefault("embedding.model_name", "qwen3-embedding-0.6b") v.SetDefault("embedding.api_endpoint", "https://aiapi.chaitin.net/v1/embeddings") diff --git a/backend/config/config.local.yaml b/backend/config/config.local.yaml new file mode 100644 index 00000000..158c70d6 --- /dev/null +++ b/backend/config/config.local.yaml @@ -0,0 +1,62 @@ +# 本地开发配置文件 - 纯YAML格式(非模版) + +base_url: http://localhost:8080 + +# 启用调试模式 +debug: true + +logger: + level: debug + +server: + addr: :8080 + port: "" + +admin: + user: admin + password: admin123 + +database: + master: postgres://monkeycode:123456@localhost:5432/monkeycode?sslmode=disable&timezone=Asia/Shanghai + slave: postgres://monkeycode:123456@localhost:5432/monkeycode?sslmode=disable&timezone=Asia/Shanghai + max_open_conns: 25 + max_idle_conns: 5 + +redis: + host: localhost + port: "6379" + pass: "" + db: 0 + idle_conn: 5 + +llm_proxy: + timeout: 30s + keep_alive: 1m + client_pool_size: 5 + request_log_path: ./logs + +vscode: + vsix_file: ./static/monkeycode.vsix + +# 关闭数据上报 +data_report: + key: "" + machine_id_file: "./static/.machine_id" + +init_model: + model_name: "" + model_key: "" + model_url: "" + +extension: + baseurl: "https://release.baizhi.cloud" + limit: 1 + limit_second: 10 + +security: + queue_limit: 5 + +embedding: + model_name: "qwen3-embedding-0.6b" + api_endpoint: "https://aiapi.chaitin.net/v1/embeddings" + api_key: "" \ No newline at end of file diff --git a/backend/pkg/report/report.go b/backend/pkg/report/report.go index 57da278b..09b1a9c7 100644 --- a/backend/pkg/report/report.go +++ b/backend/pkg/report/report.go @@ -30,10 +30,15 @@ func NewReport(logger *slog.Logger, cfg *config.Config, version *version.Version u, _ := url.Parse(raw) client := request.NewClient(u.Scheme, u.Host, 30*time.Second) + // 从配置文件读取机器ID文件路径 + idFilePath := cfg.DataReport.MachineIDFile + if idFilePath == "" { + idFilePath = "/app/static/.machine_id" + } r := &Reporter{ client: client, logger: logger.With("module", "reporter"), - IDFile: "/app/static/.machine_id", + IDFile: idFilePath, cfg: cfg, version: version, } @@ -82,10 +87,34 @@ func (r *Reporter) GetMachineID() string { } func (r *Reporter) ReportInstallation() error { + // 先确保机器ID存在(无论是否上报数据) + if err := r.ensureMachineID(); err != nil { + return err + } + + // 如果密钥为空,跳过数据上报,但机器ID已经生成 + if r.cfg.DataReport.Key == "" { + r.logger.Info("data report disabled (empty key), but machine ID is ready") + return nil + } + + // 执行数据上报 + return r.Report("monkeycode-installation", InstallData{ + MachineID: r.machineID, + Version: r.version.Version(), + Timestamp: time.Now().Format(time.RFC3339), + Type: "installation", + }) +} + +// ensureMachineID 确保机器ID存在,如果不存在则生成并保存 +func (r *Reporter) ensureMachineID() error { + // 如果已经有机器ID,直接返回 if r.machineID != "" { return nil } + // 生成新的机器ID id, err := machine.GenerateMachineID() if err != nil { r.logger.With("error", err).Warn("generate machine id failed") @@ -93,6 +122,7 @@ func (r *Reporter) ReportInstallation() error { } r.machineID = id + // 保存到文件 f, err := os.Create(r.IDFile) if err != nil { r.logger.With("error", err).Warn("create machine id file failed") @@ -106,10 +136,6 @@ func (r *Reporter) ReportInstallation() error { return err } - return r.Report("monkeycode-installation", InstallData{ - MachineID: id, - Version: r.version.Version(), - Timestamp: time.Now().Format(time.RFC3339), - Type: "installation", - }) + r.logger.Info("machine id generated and saved", "file", r.IDFile) + return nil }