git-ai-control 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/COMPATIBILITY.md +10 -0
- package/README.md +21 -11
- package/bin/git-ai-control.js +20 -22
- package/package.json +6 -7
- package/plugins/upload-filter/plugin_filter_runtime.py +3 -2
- package/scripts/check.mjs +55 -0
- package/scripts/install.mjs +451 -0
- package/scripts/install.sh +1 -237
- package/scripts/platform-services.mjs +145 -0
- package/scripts/uninstall.mjs +123 -0
- package/scripts/uninstall.sh +2 -88
- package/server.py +123 -29
- package/launchagents/com.git-ai.control-panel.plist.in +0 -24
- package/launchagents/com.git-ai.skill-usage-filter.plist.in +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
本项目的所有重要变更都会记录在此文件中。
|
|
4
4
|
|
|
5
|
+
## [0.3.1] - 2026-07-30
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
|
|
9
|
+
- 重新生成前端依赖锁文件,修复 macOS、Linux 和 Windows CI 中 `npm ci` 无法复现安装的问题。
|
|
10
|
+
- CI 仅在分支推送和 Pull Request 时运行,避免版本标签重复触发同一检查。
|
|
11
|
+
|
|
12
|
+
## [0.3.0] - 2026-07-30
|
|
13
|
+
|
|
14
|
+
### 新增
|
|
15
|
+
|
|
16
|
+
- 支持通过同一条 `npx git-ai-control start` 命令安装到 macOS、Linux 和 Windows;
|
|
17
|
+
- 新增 macOS LaunchAgent、Linux systemd user 和 Windows 任务计划程序适配;
|
|
18
|
+
- 新增跨平台 Python、Git AI 二进制和 Git 可执行文件检测;
|
|
19
|
+
- 新增 `npx git-ai-control uninstall` 跨平台卸载命令;
|
|
20
|
+
- 新增 macOS、Ubuntu、Windows 的 GitHub Actions 检查矩阵和服务定义测试。
|
|
21
|
+
|
|
22
|
+
### 变更
|
|
23
|
+
|
|
24
|
+
- 控制页面的服务状态与重启接口改为按当前操作系统执行;
|
|
25
|
+
- 安装、端点备份、运行时复制和健康检查统一由 Node.js 安装器管理;
|
|
26
|
+
- 文档补充三平台安装条件、服务管理方式和文件位置。
|
|
27
|
+
|
|
5
28
|
## [0.2.0] - 2026-07-30
|
|
6
29
|
|
|
7
30
|
### 新增
|
package/COMPATIBILITY.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Git AI 兼容性说明
|
|
2
2
|
|
|
3
|
+
## 操作系统
|
|
4
|
+
|
|
5
|
+
`npx git-ai-control start` 支持 macOS、Linux 和 Windows,三个系统共用相同的配置格式、过滤运行时和 Web 页面,仅用户级服务管理方式不同:
|
|
6
|
+
|
|
7
|
+
- macOS:LaunchAgent;
|
|
8
|
+
- Linux:systemd user;
|
|
9
|
+
- Windows:任务计划程序。
|
|
10
|
+
|
|
11
|
+
Linux 需要可用的 systemd 用户会话。Windows 需要当前用户拥有创建登录任务的权限。安装器会从 `PATH` 自动寻找 Python 3,并按当前系统检测 `git-ai` 或 `git-ai.exe`。
|
|
12
|
+
|
|
3
13
|
## 结论
|
|
4
14
|
|
|
5
15
|
本项目同时支持两类 Git AI,但支持层级不同:
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
公司统一安装了 Git AI,但不想让私人 GitHub 项目的仓库名、路径、分支或 Skill 使用情况被上报?可以试试 Git AI Control Panel。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
它是一个支持 macOS、Linux 和 Windows 的 Git AI 本地配置与上传策略管理页面:不用手改 JSON,也不用为每条隐私规则编写脚本,就能按仓库主机控制允许上传的数据类型和字段。前端使用 React、Vite 与 shadcn/ui,Web 服务只监听 `127.0.0.1:38742`,不会向局域网或公网开放。
|
|
6
6
|
|
|
7
7
|
> [!IMPORTANT]
|
|
8
8
|
> 项目可以识别 `custom_metrics` 定制版和官方 [`git-ai-project/git-ai`](https://github.com/git-ai-project/git-ai),但两者支持层级不同。仓库级事件开关、字段脱敏和 Skill 过滤目前需要 `custom_metrics` 扩展点;官方版只能管理 Git AI 已公开的原生配置。安装前请阅读[兼容性说明](COMPATIBILITY.md)。
|
|
@@ -34,10 +34,11 @@
|
|
|
34
34
|
|
|
35
35
|
### 1. 一条命令启动
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
支持 macOS、Linux 和 Windows,需要 Node.js 18+、Python 3,并要求 Git AI 已安装在默认目录:
|
|
38
38
|
|
|
39
39
|
```text
|
|
40
|
-
~/.git-ai/bin/git-ai
|
|
40
|
+
macOS / Linux: ~/.git-ai/bin/git-ai
|
|
41
|
+
Windows: %USERPROFILE%\.git-ai\bin\git-ai.exe
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
确认文件存在后运行:
|
|
@@ -52,7 +53,7 @@ npx git-ai-control start
|
|
|
52
53
|
2. 将原始上报端点备份到仅当前用户可读的本机配置;
|
|
53
54
|
3. 安装控制页面和上传过滤运行时;
|
|
54
55
|
4. 保留已有的 `config.json` 与 `filter_plugins.json`;
|
|
55
|
-
5.
|
|
56
|
+
5. 通过当前系统的用户级服务管理器创建并启动两个本机服务;
|
|
56
57
|
6. 等待控制页面和过滤服务通过健康检查。
|
|
57
58
|
|
|
58
59
|
如果浏览器没有自动打开,可以手动访问:
|
|
@@ -63,6 +64,14 @@ http://127.0.0.1:38742
|
|
|
63
64
|
|
|
64
65
|
页面顶部会显示当前 Git AI 发行版、过滤接管状态和服务状态。
|
|
65
66
|
|
|
67
|
+
各系统使用的服务管理方式:
|
|
68
|
+
|
|
69
|
+
| 系统 | 服务管理器 | 使用条件 |
|
|
70
|
+
| --- | --- | --- |
|
|
71
|
+
| macOS | LaunchAgent | 当前图形用户会话 |
|
|
72
|
+
| Linux | systemd user | 可用的 systemd 用户会话 |
|
|
73
|
+
| Windows | 任务计划程序 | Windows 10/11,当前用户可创建登录任务 |
|
|
74
|
+
|
|
66
75
|
### 2. 配置仓库插件
|
|
67
76
|
|
|
68
77
|
以“GitHub 私人仓库只允许上传 Token”为例:
|
|
@@ -122,23 +131,24 @@ Git AI
|
|
|
122
131
|
| 内容 | 位置 |
|
|
123
132
|
| --- | --- |
|
|
124
133
|
| 过滤运行时源码 | `plugins/upload-filter/plugin_filter_runtime.py` |
|
|
125
|
-
|
|
|
126
|
-
|
|
|
134
|
+
| 跨平台安装器 | `scripts/install.mjs`、`scripts/uninstall.mjs` |
|
|
135
|
+
| 服务适配器 | `scripts/platform-services.mjs` |
|
|
127
136
|
| Git AI 原生配置 | `~/.git-ai/config.json` |
|
|
128
137
|
| 插件策略 | `~/.git-ai/filter_plugins.json` |
|
|
129
138
|
| 原上报端点本机备份 | `~/.git-ai/upstream_metrics.json` |
|
|
130
139
|
| 过滤运行时安装副本 | `~/.git-ai/filters/plugin_filter_runtime.py` |
|
|
131
140
|
| Web 服务安装副本 | `~/.git-ai/control-panel` |
|
|
132
|
-
|
|
|
133
|
-
|
|
|
141
|
+
| macOS 服务定义 | `~/Library/LaunchAgents/com.git-ai.*.plist` |
|
|
142
|
+
| Linux 服务定义 | `~/.config/systemd/user/git-ai-*.service` |
|
|
143
|
+
| Windows 服务定义 | `%USERPROFILE%\.git-ai\services\*.ps1` 与任务计划程序 |
|
|
134
144
|
|
|
135
145
|
## 卸载
|
|
136
146
|
|
|
137
147
|
```bash
|
|
138
|
-
|
|
148
|
+
npx git-ai-control uninstall
|
|
139
149
|
```
|
|
140
150
|
|
|
141
|
-
|
|
151
|
+
卸载命令会停止两个服务、删除本项目安装的程序副本,并将上报端点恢复为 Git AI 原地址。`config.json`、`filter_plugins.json` 和日志会保留。
|
|
142
152
|
|
|
143
153
|
## 参与贡献
|
|
144
154
|
|
|
@@ -157,7 +167,7 @@ npm ci
|
|
|
157
167
|
npm run lint
|
|
158
168
|
npm run build
|
|
159
169
|
cd ../..
|
|
160
|
-
|
|
170
|
+
npm run check
|
|
161
171
|
```
|
|
162
172
|
|
|
163
173
|
提交 Pull Request 时请说明:
|
package/bin/git-ai-control.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { fileURLToPath } from "node:url"
|
|
3
|
+
import {spawnSync} from "node:child_process"
|
|
5
4
|
import path from "node:path"
|
|
5
|
+
import {fileURLToPath} from "node:url"
|
|
6
|
+
|
|
7
|
+
import {browserCommand} from "../scripts/platform-services.mjs"
|
|
6
8
|
|
|
7
9
|
const command = process.argv[2]
|
|
8
10
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
@@ -13,6 +15,7 @@ function printHelp() {
|
|
|
13
15
|
|
|
14
16
|
用法:
|
|
15
17
|
git-ai-control start 安装或更新本机服务,并打开配置页面
|
|
18
|
+
git-ai-control uninstall 卸载本机服务并恢复上报端点
|
|
16
19
|
git-ai-control --help 显示帮助`)
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -21,37 +24,32 @@ if (command === "--help" || command === "-h" || !command) {
|
|
|
21
24
|
process.exit(0)
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
if (
|
|
27
|
+
if (!["start", "uninstall"].includes(command)) {
|
|
25
28
|
console.error(`未知命令:${command}`)
|
|
26
29
|
printHelp()
|
|
27
30
|
process.exit(1)
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (command === "uninstall") {
|
|
35
|
+
const {uninstall} = await import("../scripts/uninstall.mjs")
|
|
36
|
+
await uninstall()
|
|
37
|
+
process.exit(0)
|
|
38
|
+
}
|
|
39
|
+
const {install} = await import("../scripts/install.mjs")
|
|
40
|
+
await install()
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(`${command === "start" ? "安装" : "卸载"}失败:${error.message}`)
|
|
32
43
|
process.exit(1)
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
env: process.env,
|
|
38
|
-
stdio: "inherit",
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
if (installResult.error) {
|
|
42
|
-
console.error(`安装失败:${installResult.error.message}`)
|
|
43
|
-
process.exit(1)
|
|
44
|
-
}
|
|
45
|
-
if (installResult.status !== 0) {
|
|
46
|
-
process.exit(installResult.status ?? 1)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const openResult = spawnSync("/usr/bin/open", [controlPanelUrl], {
|
|
46
|
+
const opener = browserCommand(process.platform, controlPanelUrl)
|
|
47
|
+
const openResult = opener && spawnSync(opener.command, opener.args, {
|
|
50
48
|
stdio: "ignore",
|
|
51
49
|
})
|
|
52
|
-
if (openResult.error || openResult.status !== 0) {
|
|
50
|
+
if (!openResult || openResult.error || openResult.status !== 0) {
|
|
53
51
|
console.error(`服务已启动,请手动访问 ${controlPanelUrl}`)
|
|
54
|
-
process.exit(
|
|
52
|
+
process.exit(0)
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
console.log(`已打开 Git AI 配置中心:${controlPanelUrl}`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-ai-control",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Git AI 本地配置与上传隐私控制面板",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
11
|
"docs",
|
|
12
|
-
"launchagents",
|
|
13
12
|
"plugins",
|
|
14
13
|
"scripts",
|
|
15
14
|
"static",
|
|
@@ -20,19 +19,19 @@
|
|
|
20
19
|
"server.py"
|
|
21
20
|
],
|
|
22
21
|
"scripts": {
|
|
23
|
-
"
|
|
22
|
+
"test": "node --test",
|
|
23
|
+
"check": "node bin/git-ai-control.js --help && node scripts/check.mjs && npm test"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18"
|
|
27
27
|
},
|
|
28
|
-
"os": [
|
|
29
|
-
"darwin"
|
|
30
|
-
],
|
|
31
28
|
"keywords": [
|
|
32
29
|
"git-ai",
|
|
33
30
|
"privacy",
|
|
34
31
|
"telemetry",
|
|
35
|
-
"macos"
|
|
32
|
+
"macos",
|
|
33
|
+
"linux",
|
|
34
|
+
"windows"
|
|
36
35
|
],
|
|
37
36
|
"repository": {
|
|
38
37
|
"type": "git",
|
|
@@ -32,8 +32,9 @@ EVENT_TYPES = {
|
|
|
32
32
|
|
|
33
33
|
HOST = "127.0.0.1"
|
|
34
34
|
PORT = 38741
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
GIT_AI_ROOT = Path(os.environ.get("GIT_AI_ROOT", Path.home() / ".git-ai")).resolve()
|
|
36
|
+
POLICY_CONFIG_PATH = GIT_AI_ROOT / "filter_plugins.json"
|
|
37
|
+
UPSTREAM_CONFIG_PATH = GIT_AI_ROOT / "upstream_metrics.json"
|
|
37
38
|
OWNER_REPOSITORY_PATTERN = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:\.git)?$")
|
|
38
39
|
SKILL_KEYS = {"skillName", "skill", "name"}
|
|
39
40
|
PATH_KEYS = {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {spawnSync} from "node:child_process"
|
|
2
|
+
|
|
3
|
+
function run(command, args, options = {}) {
|
|
4
|
+
const result = spawnSync(command, args, {
|
|
5
|
+
encoding: "utf8",
|
|
6
|
+
stdio: options.capture ? "pipe" : "inherit",
|
|
7
|
+
})
|
|
8
|
+
if (result.error || result.status !== 0) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const pythonCandidates = process.platform === "win32"
|
|
15
|
+
? [["py", ["-3"]], ["python", []], ["python3", []]]
|
|
16
|
+
: [["python3", []], ["python", []]]
|
|
17
|
+
const pythonCommand = pythonCandidates.find(([command, prefix]) =>
|
|
18
|
+
run(command, [...prefix, "--version"], {capture: true}),
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if (!pythonCommand) {
|
|
22
|
+
console.error("检查失败:未找到 Python 3")
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const [python, prefix] = pythonCommand
|
|
27
|
+
if (
|
|
28
|
+
!run(python, [
|
|
29
|
+
...prefix,
|
|
30
|
+
"-m",
|
|
31
|
+
"py_compile",
|
|
32
|
+
"server.py",
|
|
33
|
+
"plugins/upload-filter/plugin_filter_runtime.py",
|
|
34
|
+
])
|
|
35
|
+
) {
|
|
36
|
+
process.exit(1)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const file of [
|
|
40
|
+
"bin/git-ai-control.js",
|
|
41
|
+
"scripts/check.mjs",
|
|
42
|
+
"scripts/install.mjs",
|
|
43
|
+
"scripts/platform-services.mjs",
|
|
44
|
+
"scripts/uninstall.mjs",
|
|
45
|
+
]) {
|
|
46
|
+
if (!run(process.execPath, ["--check", file])) {
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (process.platform !== "win32") {
|
|
52
|
+
if (!run("/bin/sh", ["-n", "scripts/install.sh", "scripts/uninstall.sh"])) {
|
|
53
|
+
process.exit(1)
|
|
54
|
+
}
|
|
55
|
+
}
|