antigravity-acp-sdk 0.1.0__tar.gz

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.
Files changed (24) hide show
  1. antigravity_acp_sdk-0.1.0/PKG-INFO +186 -0
  2. antigravity_acp_sdk-0.1.0/README.md +178 -0
  3. antigravity_acp_sdk-0.1.0/pyproject.toml +33 -0
  4. antigravity_acp_sdk-0.1.0/setup.cfg +4 -0
  5. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/__init__.py +12 -0
  6. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/access_control_rules.json +20 -0
  7. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/hooks.json +39 -0
  8. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/mcp_config.json +1 -0
  9. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/scripts/_shared.py +119 -0
  10. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/scripts/check_file_access.py +127 -0
  11. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/scripts/validate.py +159 -0
  12. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/agent/scripts/validate_delivery.py +220 -0
  13. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/client.py +442 -0
  14. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/inspector.py +221 -0
  15. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/pool.py +79 -0
  16. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/sync_schema.py +76 -0
  17. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk/verify.py +158 -0
  18. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/PKG-INFO +186 -0
  19. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/SOURCES.txt +22 -0
  20. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/dependency_links.txt +1 -0
  21. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/entry_points.txt +4 -0
  22. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/requires.txt +1 -0
  23. antigravity_acp_sdk-0.1.0/src/antigravity_acp_sdk.egg-info/top_level.txt +1 -0
  24. antigravity_acp_sdk-0.1.0/tests/test_client_pool.py +763 -0
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.4
2
+ Name: antigravity-acp-sdk
3
+ Version: 0.1.0
4
+ Summary: A generic client and connection pool implementation for Agent Client Protocol (ACP)
5
+ Requires-Python: ==3.12.*
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: agent-client-protocol>=0.10.1
8
+
9
+ # Antigravity ACP SDK
10
+
11
+ `antigravity-acp-sdk` 是基于官方 `agent-client-protocol` (ACP) 实现的通用 Python 客户端与长连接并发池管理器。
12
+
13
+ ## 安装方式
14
+
15
+ ### 1. 本地联调模式 (开发时推荐)
16
+ 在主项目的 `pyproject.toml` 中配置本地相对路径映射:
17
+
18
+ ```toml
19
+ [project]
20
+ dependencies = [
21
+ "antigravity-acp-sdk",
22
+ ]
23
+
24
+ [tool.uv.sources]
25
+ antigravity-acp-sdk = { path = "antigravity-acp-sdk", editable = true }
26
+ ```
27
+
28
+ ### 2. Git 依赖模式
29
+ 直接指向远程 Git 仓库:
30
+
31
+ ```toml
32
+ [project]
33
+ dependencies = [
34
+ "antigravity-acp-sdk @ git+ssh://git@github.com/yourorg/antigravity-acp-sdk.git@v0.1.0"
35
+ ]
36
+ ```
37
+
38
+ ## 系统环境依赖与安装
39
+
40
+ 本包运行依赖于 `agy` CLI 命令行工具以及 `agy-acp` 通信桥接可执行程序。任何引入本包的项目环境均需要预先下载并安装这两个系统级依赖。
41
+
42
+ ### 1. 安装官方 agy CLI
43
+ `agy` 是运行智能体的底层命令行工具。可以通过官方安装脚本进行安装:
44
+ ```bash
45
+ curl -fsSL https://antigravity.google/cli/install.sh | bash
46
+ # 默认会安装到 ~/.local/bin/agy。为了让系统全局可用,建议将其移动到 /usr/local/bin:
47
+ # mv ~/.local/bin/agy /usr/local/bin/agy
48
+ ```
49
+
50
+ ### 2. 下载并安装 agy-acp
51
+ `agy-acp` 是连接池直接拉起长连接的 stdio 桥接执行文件:
52
+ * **下载地址**:`https://www.fentaiq.com:543/agy-acp`
53
+ * **安装命令**:
54
+ ```bash
55
+ curl -fsSL https://www.fentaiq.com:543/agy-acp -o /usr/local/bin/agy-acp
56
+ chmod +x /usr/local/bin/agy-acp
57
+ ```
58
+
59
+ ### 3. 环境与 PATH 变量配置
60
+ 默认情况下,连接池会在系统的 `PATH` 环境变量中查找 `agy-acp`。
61
+ * 如果 `agy-acp` 被安装到标准的 `/usr/local/bin` 中,连接池可自动直接调用。
62
+ * 如果安装在非标准路径(例如本地 Python 虚拟环境 `.venv/bin` 或用户的本地二进制目录 `~/.local/bin`),则必须在初始化连接池时通过 `extra_paths` 参数将该目录传入,例如 `extra_paths=["/home/user/.local/bin"]`,否则会抛出子进程启动找不到命令的错误。
63
+
64
+ ## 环境变量与运行配置
65
+
66
+ 本包在拉起 ACP 子进程时,会自动同步并支持以下关键环境变量以控制智能体的底层行为。使用本包的项目应在启动前配置这些环境变量:
67
+
68
+ 1. **模型指定 (`AGY_MODEL`)**:
69
+ * 通过环境变量 `AGY_MODEL` 设定 ACP 进程的默认分析模型(如 `"Gemini 3.5 Flash (Medium)"`)。
70
+ 2. **ACP 额外运行参数 (`AGY_EXTRA_ARGS`)**:
71
+ * 默认会自动注入参数:`--dangerously-skip-permissions --print-timeout=10m0s`。这对于自动化测试和无人工介入运行(Non-interactive)场景非常关键,用以绕过命令行交互权限确认并防止指令超时。
72
+
73
+ ## 智能体配置与资产结构规范 (By Convention)
74
+
75
+ 本 SDK 采用**约定优于配置(Convention over Configuration)**的策略:
76
+
77
+ ### 1. 目录即智能体命名约定(强制要求)
78
+ 所有智能体必须在统一的 `agent/` 文件夹下进行组织,**子目录名称必须作为智能体的名称,且必须包含 AGENTS.md 作为合法智能体标识**:
79
+ ```text
80
+ host_project/
81
+ └── agent/
82
+ ├── mcp_config.json # 1. 全局默认 MCP 配置文件 (所有 Agent 共享)
83
+ ├── hooks.json # 2. 全局默认 Hooks 配置文件 (所有 Agent 共享)
84
+ ├── access_control_rules.json # 3. 全局默认访问控制阻断文件 (所有 Agent 共享)
85
+ ├── scripts/ # 4. 全局公用钩子脚本目录
86
+ │ ├── _shared.py
87
+ │ ├── validate.py
88
+ │ ├── validate_delivery.py
89
+ │ └── check_file_access.py
90
+ └── stock_analyzer/ # 5. 智能体专属配置目录 (名称: stock_analyzer)
91
+ ├── AGENTS.md # 专属规则 (Rules - 必须存在)
92
+ ├── mcp_config.json # 专属 MCP 配置文件 (可选)
93
+ ├── hooks.json # 专属规则挂钩文件 (可选)
94
+ ├── access_control_rules.json # 专属访问控制挂钩文件 (可选)
95
+ └── skills/ # 专属技能目录 (Skills)
96
+ └── stock_analysis/
97
+ ```
98
+
99
+ ### 2. 三层配置深度合并机制 (Triple-Layered Deep Merge)
100
+ 在启动工作区时,SDK 会自动将三层配置进行深度合并,生成最终沙箱 `<cwd>/.agents/` 下对应的配置文件:
101
+ * **JSON 配置合并语义 (Overwrite)**:
102
+ * 字典(dict)类型:执行递归深度合并。相同 key 值以高优先级层级覆盖。
103
+ * 非字典(如 list、scalar)类型:**直接覆盖(Overwrite)**,高优先级配置整段替换低优先级。
104
+ * **同名文件夹合并**:
105
+ * 三层中同名文件夹(如 `skills/`、`scripts/` 等资源目录)会递归拷贝并合并至沙箱。
106
+ * 如果拷贝中发现同名文件冲突,拷贝过程将产生警告记录。
107
+
108
+ ---
109
+
110
+ ## 核心接口说明
111
+
112
+ ### 1. 连接池初始化 (极简无参化)
113
+ ```python
114
+ from antigravity_acp_sdk import AcpConnectionPool
115
+
116
+ pool = AcpConnectionPool.get_instance(
117
+ max_connections=4,
118
+ command="agy-acp",
119
+ extra_paths=["/path/to/custom/bin"]
120
+ )
121
+ ```
122
+
123
+ ### 2. 获取连接与输入编译 (`client.new_session`)
124
+ 支持传入 `inputs` 字典对规则和技能的 Markdown 模板进行安全变量编译(支持可选变量 `{{ x | default('') }}`),并自动处理文件输入拷贝。
125
+
126
+ ```python
127
+ from antigravity_acp_sdk import AgentManager
128
+
129
+ # 初始化智能体定义
130
+ manager = AgentManager("agent")
131
+ agent = manager.get_agent("stock_analyzer")
132
+
133
+ # 申请连接
134
+ client = await pool.acquire()
135
+
136
+ # 开启会话,传入 inputs 字典自动处理拷贝与模板渲染
137
+ session_resp = await client.new_session(
138
+ cwd="/path/to/sandbox",
139
+ agent=agent,
140
+ inputs={
141
+ "financial_data": "/abs/path/to/annual_financial_metrics.tsv", # 路径:将自动拷贝到 .agents/input/ 并替换为相对路径
142
+ "analysis_guideline": "注重对资产流动性指标的审核" # 文本:直接执行模板变量替换
143
+ }
144
+ )
145
+ session_id = session_resp.session_id
146
+ ```
147
+
148
+ ### 3. 一键运行与交付物自动回收 (`client.prompt`)
149
+ 宿主使用 `client.prompt` 启动智能体。SDK 会在内存中读取并自动解析 `.agents/output/` 目录下的所有产出(封装为 `AgentOutputs` 对象),随即物理清空 `input/` 与 `output/` 临时资源目录,宿主无须关心清理细节。
150
+
151
+ ```python
152
+ from acp import text_block
153
+
154
+ # 运行并回收成果
155
+ prompt_resp, outputs = await client.prompt(
156
+ session_id=session_id,
157
+ prompt=[text_block("Use skill: stock_analysis, 分析股票 000001.SZ")]
158
+ )
159
+
160
+ # 1. 自动解析为 dict (针对 .json)
161
+ report = outputs.get_content("report.json")
162
+ # 2. 读取为普通文本 (针对其他格式)
163
+ text_log = outputs.get_content("sub_folder/logs.txt")
164
+ ```
165
+
166
+ ---
167
+
168
+ ## 命令行开发辅助与诊断工具 (Bin CLI Tools)
169
+
170
+ ### 1. verify-mcp:MCP 连通性一键诊断
171
+ 一键对三层合并后的特定智能体 MCP 进程执行 standard 初始化握手诊断:
172
+ ```bash
173
+ uv run verify-mcp stock_analyzer --base-dir agent/ --extra-paths .venv/bin
174
+ ```
175
+
176
+ ### 2. inspect-agent:智能体配置及沙箱结构大盘点
177
+ 交互式盘点其规则、技能和 Hooks,输出生成的 `.agents/` 目标沙箱结构:
178
+ ```bash
179
+ uv run inspect-agent --base-dir agent/ --extra-paths .venv/bin
180
+ ```
181
+
182
+ ### 3. sync-schema:Pydantic 类 Schema 导出
183
+ 将开发环境定义的 Pydantic 类一键同步至智能体 schemas 目录下:
184
+ ```bash
185
+ uv run sync-schema -f src/stock_data_fetcher/analysis/models.py -c StockAnalysisReport -o agent/stock_analyzer/schemas/report.schema.json
186
+ ```
@@ -0,0 +1,178 @@
1
+ # Antigravity ACP SDK
2
+
3
+ `antigravity-acp-sdk` 是基于官方 `agent-client-protocol` (ACP) 实现的通用 Python 客户端与长连接并发池管理器。
4
+
5
+ ## 安装方式
6
+
7
+ ### 1. 本地联调模式 (开发时推荐)
8
+ 在主项目的 `pyproject.toml` 中配置本地相对路径映射:
9
+
10
+ ```toml
11
+ [project]
12
+ dependencies = [
13
+ "antigravity-acp-sdk",
14
+ ]
15
+
16
+ [tool.uv.sources]
17
+ antigravity-acp-sdk = { path = "antigravity-acp-sdk", editable = true }
18
+ ```
19
+
20
+ ### 2. Git 依赖模式
21
+ 直接指向远程 Git 仓库:
22
+
23
+ ```toml
24
+ [project]
25
+ dependencies = [
26
+ "antigravity-acp-sdk @ git+ssh://git@github.com/yourorg/antigravity-acp-sdk.git@v0.1.0"
27
+ ]
28
+ ```
29
+
30
+ ## 系统环境依赖与安装
31
+
32
+ 本包运行依赖于 `agy` CLI 命令行工具以及 `agy-acp` 通信桥接可执行程序。任何引入本包的项目环境均需要预先下载并安装这两个系统级依赖。
33
+
34
+ ### 1. 安装官方 agy CLI
35
+ `agy` 是运行智能体的底层命令行工具。可以通过官方安装脚本进行安装:
36
+ ```bash
37
+ curl -fsSL https://antigravity.google/cli/install.sh | bash
38
+ # 默认会安装到 ~/.local/bin/agy。为了让系统全局可用,建议将其移动到 /usr/local/bin:
39
+ # mv ~/.local/bin/agy /usr/local/bin/agy
40
+ ```
41
+
42
+ ### 2. 下载并安装 agy-acp
43
+ `agy-acp` 是连接池直接拉起长连接的 stdio 桥接执行文件:
44
+ * **下载地址**:`https://www.fentaiq.com:543/agy-acp`
45
+ * **安装命令**:
46
+ ```bash
47
+ curl -fsSL https://www.fentaiq.com:543/agy-acp -o /usr/local/bin/agy-acp
48
+ chmod +x /usr/local/bin/agy-acp
49
+ ```
50
+
51
+ ### 3. 环境与 PATH 变量配置
52
+ 默认情况下,连接池会在系统的 `PATH` 环境变量中查找 `agy-acp`。
53
+ * 如果 `agy-acp` 被安装到标准的 `/usr/local/bin` 中,连接池可自动直接调用。
54
+ * 如果安装在非标准路径(例如本地 Python 虚拟环境 `.venv/bin` 或用户的本地二进制目录 `~/.local/bin`),则必须在初始化连接池时通过 `extra_paths` 参数将该目录传入,例如 `extra_paths=["/home/user/.local/bin"]`,否则会抛出子进程启动找不到命令的错误。
55
+
56
+ ## 环境变量与运行配置
57
+
58
+ 本包在拉起 ACP 子进程时,会自动同步并支持以下关键环境变量以控制智能体的底层行为。使用本包的项目应在启动前配置这些环境变量:
59
+
60
+ 1. **模型指定 (`AGY_MODEL`)**:
61
+ * 通过环境变量 `AGY_MODEL` 设定 ACP 进程的默认分析模型(如 `"Gemini 3.5 Flash (Medium)"`)。
62
+ 2. **ACP 额外运行参数 (`AGY_EXTRA_ARGS`)**:
63
+ * 默认会自动注入参数:`--dangerously-skip-permissions --print-timeout=10m0s`。这对于自动化测试和无人工介入运行(Non-interactive)场景非常关键,用以绕过命令行交互权限确认并防止指令超时。
64
+
65
+ ## 智能体配置与资产结构规范 (By Convention)
66
+
67
+ 本 SDK 采用**约定优于配置(Convention over Configuration)**的策略:
68
+
69
+ ### 1. 目录即智能体命名约定(强制要求)
70
+ 所有智能体必须在统一的 `agent/` 文件夹下进行组织,**子目录名称必须作为智能体的名称,且必须包含 AGENTS.md 作为合法智能体标识**:
71
+ ```text
72
+ host_project/
73
+ └── agent/
74
+ ├── mcp_config.json # 1. 全局默认 MCP 配置文件 (所有 Agent 共享)
75
+ ├── hooks.json # 2. 全局默认 Hooks 配置文件 (所有 Agent 共享)
76
+ ├── access_control_rules.json # 3. 全局默认访问控制阻断文件 (所有 Agent 共享)
77
+ ├── scripts/ # 4. 全局公用钩子脚本目录
78
+ │ ├── _shared.py
79
+ │ ├── validate.py
80
+ │ ├── validate_delivery.py
81
+ │ └── check_file_access.py
82
+ └── stock_analyzer/ # 5. 智能体专属配置目录 (名称: stock_analyzer)
83
+ ├── AGENTS.md # 专属规则 (Rules - 必须存在)
84
+ ├── mcp_config.json # 专属 MCP 配置文件 (可选)
85
+ ├── hooks.json # 专属规则挂钩文件 (可选)
86
+ ├── access_control_rules.json # 专属访问控制挂钩文件 (可选)
87
+ └── skills/ # 专属技能目录 (Skills)
88
+ └── stock_analysis/
89
+ ```
90
+
91
+ ### 2. 三层配置深度合并机制 (Triple-Layered Deep Merge)
92
+ 在启动工作区时,SDK 会自动将三层配置进行深度合并,生成最终沙箱 `<cwd>/.agents/` 下对应的配置文件:
93
+ * **JSON 配置合并语义 (Overwrite)**:
94
+ * 字典(dict)类型:执行递归深度合并。相同 key 值以高优先级层级覆盖。
95
+ * 非字典(如 list、scalar)类型:**直接覆盖(Overwrite)**,高优先级配置整段替换低优先级。
96
+ * **同名文件夹合并**:
97
+ * 三层中同名文件夹(如 `skills/`、`scripts/` 等资源目录)会递归拷贝并合并至沙箱。
98
+ * 如果拷贝中发现同名文件冲突,拷贝过程将产生警告记录。
99
+
100
+ ---
101
+
102
+ ## 核心接口说明
103
+
104
+ ### 1. 连接池初始化 (极简无参化)
105
+ ```python
106
+ from antigravity_acp_sdk import AcpConnectionPool
107
+
108
+ pool = AcpConnectionPool.get_instance(
109
+ max_connections=4,
110
+ command="agy-acp",
111
+ extra_paths=["/path/to/custom/bin"]
112
+ )
113
+ ```
114
+
115
+ ### 2. 获取连接与输入编译 (`client.new_session`)
116
+ 支持传入 `inputs` 字典对规则和技能的 Markdown 模板进行安全变量编译(支持可选变量 `{{ x | default('') }}`),并自动处理文件输入拷贝。
117
+
118
+ ```python
119
+ from antigravity_acp_sdk import AgentManager
120
+
121
+ # 初始化智能体定义
122
+ manager = AgentManager("agent")
123
+ agent = manager.get_agent("stock_analyzer")
124
+
125
+ # 申请连接
126
+ client = await pool.acquire()
127
+
128
+ # 开启会话,传入 inputs 字典自动处理拷贝与模板渲染
129
+ session_resp = await client.new_session(
130
+ cwd="/path/to/sandbox",
131
+ agent=agent,
132
+ inputs={
133
+ "financial_data": "/abs/path/to/annual_financial_metrics.tsv", # 路径:将自动拷贝到 .agents/input/ 并替换为相对路径
134
+ "analysis_guideline": "注重对资产流动性指标的审核" # 文本:直接执行模板变量替换
135
+ }
136
+ )
137
+ session_id = session_resp.session_id
138
+ ```
139
+
140
+ ### 3. 一键运行与交付物自动回收 (`client.prompt`)
141
+ 宿主使用 `client.prompt` 启动智能体。SDK 会在内存中读取并自动解析 `.agents/output/` 目录下的所有产出(封装为 `AgentOutputs` 对象),随即物理清空 `input/` 与 `output/` 临时资源目录,宿主无须关心清理细节。
142
+
143
+ ```python
144
+ from acp import text_block
145
+
146
+ # 运行并回收成果
147
+ prompt_resp, outputs = await client.prompt(
148
+ session_id=session_id,
149
+ prompt=[text_block("Use skill: stock_analysis, 分析股票 000001.SZ")]
150
+ )
151
+
152
+ # 1. 自动解析为 dict (针对 .json)
153
+ report = outputs.get_content("report.json")
154
+ # 2. 读取为普通文本 (针对其他格式)
155
+ text_log = outputs.get_content("sub_folder/logs.txt")
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 命令行开发辅助与诊断工具 (Bin CLI Tools)
161
+
162
+ ### 1. verify-mcp:MCP 连通性一键诊断
163
+ 一键对三层合并后的特定智能体 MCP 进程执行 standard 初始化握手诊断:
164
+ ```bash
165
+ uv run verify-mcp stock_analyzer --base-dir agent/ --extra-paths .venv/bin
166
+ ```
167
+
168
+ ### 2. inspect-agent:智能体配置及沙箱结构大盘点
169
+ 交互式盘点其规则、技能和 Hooks,输出生成的 `.agents/` 目标沙箱结构:
170
+ ```bash
171
+ uv run inspect-agent --base-dir agent/ --extra-paths .venv/bin
172
+ ```
173
+
174
+ ### 3. sync-schema:Pydantic 类 Schema 导出
175
+ 将开发环境定义的 Pydantic 类一键同步至智能体 schemas 目录下:
176
+ ```bash
177
+ uv run sync-schema -f src/stock_data_fetcher/analysis/models.py -c StockAnalysisReport -o agent/stock_analyzer/schemas/report.schema.json
178
+ ```
@@ -0,0 +1,33 @@
1
+ [project]
2
+ name = "antigravity-acp-sdk"
3
+ version = "0.1.0"
4
+ description = "A generic client and connection pool implementation for Agent Client Protocol (ACP)"
5
+ readme = "README.md"
6
+ requires-python = "==3.12.*"
7
+ dependencies = [
8
+ "agent-client-protocol>=0.10.1",
9
+ ]
10
+
11
+ [project.scripts]
12
+ verify-mcp = "antigravity_acp_sdk.verify:main"
13
+ inspect-agent = "antigravity_acp_sdk.inspector:main"
14
+ sync-schema = "antigravity_acp_sdk.sync_schema:main"
15
+
16
+ [build-system]
17
+ requires = ["setuptools>=61.0"]
18
+ build-backend = "setuptools.build_meta"
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["src"]
22
+
23
+ [tool.setuptools.package-data]
24
+ antigravity_acp_sdk = [
25
+ "agent/*.json",
26
+ "agent/scripts/*.py"
27
+ ]
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "pytest>=8.4.2",
32
+ "pytest-asyncio>=0.23.7",
33
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ from antigravity_acp_sdk.client import AGYClient, AcpClient, ACPAgent, AgentManager
2
+ from antigravity_acp_sdk.verify import verify_mcp_config
3
+ from antigravity_acp_sdk.pool import AcpConnectionPool
4
+
5
+ __all__ = [
6
+ "AGYClient",
7
+ "AcpClient",
8
+ "AcpConnectionPool",
9
+ "ACPAgent",
10
+ "AgentManager",
11
+ "verify_mcp_config"
12
+ ]
@@ -0,0 +1,20 @@
1
+ {
2
+ "rules": [
3
+ {
4
+ "name": ".system_scripts_block",
5
+ "path_patterns": [".agents/scripts/"],
6
+ "extensions": [".py"],
7
+ "exclude_patterns": [],
8
+ "allow": false,
9
+ "reason": "❌ 访问拦截警告:你不应该阅读并关心系统代码文件!\n提醒:你的身份是 institutional investment analyst (世界级定量与基本面投资分析师),你的主要工作是阅读和分析财务数据,而非审计、调试或探究系统底层的 Python 校验脚本代码。请回归财务数据分析逻辑。"
10
+ },
11
+ {
12
+ "name": ".system_view_file_protection",
13
+ "path_patterns": [".agents/hooks.json", ".agents/mcp_config.json", ".agents/access_control_rules.json"],
14
+ "extensions": [],
15
+ "exclude_patterns": [],
16
+ "allow": false,
17
+ "reason": "❌ 访问拦截警告:你不应该阅读并关心系统的配置文件!"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "json-validation-hook": {
3
+ "enabled": true,
4
+ "PreToolUse": [
5
+ {
6
+ "matcher": "write_to_file|replace_file_content|multi_replace_file_content",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "python3 scripts/check_file_access.py",
11
+ "timeout": 5
12
+ },
13
+ {
14
+ "type": "command",
15
+ "command": "python3 scripts/validate.py",
16
+ "timeout": 10
17
+ }
18
+ ]
19
+ },
20
+ {
21
+ "matcher": "view_file|list_dir",
22
+ "hooks": [
23
+ {
24
+ "type": "command",
25
+ "command": "python3 scripts/check_file_access.py",
26
+ "timeout": 5
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "Stop": [
32
+ {
33
+ "type": "command",
34
+ "command": "python3 scripts/validate_delivery.py",
35
+ "timeout": 15
36
+ }
37
+ ]
38
+ }
39
+ }
@@ -0,0 +1,119 @@
1
+ import os
2
+ import sys
3
+ import json
4
+ import re
5
+ import datetime
6
+
7
+ def parse_tool_call(payload: dict) -> tuple:
8
+ """
9
+ 从 Payload 中提取 tool_name 和 arguments dict,解析 argumentsJson 字符串。
10
+ """
11
+ tool_call = payload.get("toolCall", {})
12
+ tool_name = tool_call.get("name", "")
13
+ args_json = tool_call.get("argumentsJson", "{}")
14
+ try:
15
+ arguments = json.loads(args_json) if isinstance(args_json, str) else args_json
16
+ except json.JSONDecodeError:
17
+ arguments = {}
18
+ return tool_name, arguments
19
+
20
+ def resolve_cwd(payload: dict) -> str:
21
+ """
22
+ 优先使用 payload.workspacePaths,其次是 PWD,最后是 os.getcwd()。
23
+ 如果最终解析出的路径包含 .agents,则自动将其截取转换为其常态父目录,确保日志始终存放在沙箱外部。
24
+ """
25
+ cwd = None
26
+ workspace_paths = payload.get("workspacePaths", [])
27
+ if workspace_paths and workspace_paths[0]:
28
+ cwd = workspace_paths[0]
29
+
30
+ if not cwd:
31
+ cwd = os.environ.get("PWD")
32
+
33
+ if not cwd:
34
+ cwd = os.getcwd()
35
+
36
+ abs_cwd = os.path.abspath(cwd)
37
+ # 如果路径以 .agents 结尾,截取为其父目录
38
+ if abs_cwd.endswith(".agents"):
39
+ abs_cwd = os.path.dirname(abs_cwd)
40
+ elif "/.agents/" in abs_cwd:
41
+ parts = abs_cwd.split(os.sep)
42
+ if ".agents" in parts:
43
+ idx = parts.index(".agents")
44
+ abs_cwd = os.sep.join(parts[:idx])
45
+
46
+ return abs_cwd
47
+
48
+ def validate_schema(data: dict, schema: dict, path: str = "") -> tuple:
49
+ """
50
+ 递归校验 JSON 结构体是否包含 Schema 中定义的所有必填字段及正确类型。
51
+ """
52
+ required = schema.get("required", [])
53
+ for field in required:
54
+ if field not in data:
55
+ field_path = f"{path}.{field}" if path else field
56
+ return False, f"缺少必选字段 '{field_path}'"
57
+
58
+ properties = schema.get("properties", {})
59
+ for prop_name, prop_schema in properties.items():
60
+ if prop_name in data:
61
+ prop_data = data[prop_name]
62
+ prop_path = f"{path}.{prop_name}" if path else prop_name
63
+ expected_type = prop_schema.get("type")
64
+
65
+ if expected_type == "object":
66
+ if not isinstance(prop_data, dict):
67
+ return False, f"字段 '{prop_path}' 的类型应为 object (字典类型)"
68
+ is_valid, err_msg = validate_schema(prop_data, prop_schema, prop_path)
69
+ if not is_valid:
70
+ return False, err_msg
71
+ elif expected_type == "array":
72
+ if not isinstance(prop_data, list):
73
+ return False, f"字段 '{prop_path}' 的类型应为 array (列表类型)"
74
+ items_schema = prop_schema.get("items", {})
75
+ if items_schema.get("type", "object") == "object" or "required" in items_schema:
76
+ for idx, item in enumerate(prop_data):
77
+ if not isinstance(item, dict):
78
+ return False, f"字段 '{prop_path}[{idx}]' 的类型应为 object (字典类型)"
79
+ is_valid, err_msg = validate_schema(item, items_schema, f"{prop_path}[{idx}]")
80
+ if not is_valid:
81
+ return False, err_msg
82
+ return True, ""
83
+
84
+ def resolve_log_dir(cwd: str) -> str:
85
+ """
86
+ 从 ~/.gemini/antigravity-cli/cli.log 软链接解析当前会话时间戳,构造日志目录。
87
+ """
88
+ cli_log_link = os.path.expanduser("~/.gemini/antigravity-cli/cli.log")
89
+ dt_str = None
90
+ try:
91
+ if os.path.islink(cli_log_link):
92
+ target = os.readlink(cli_log_link)
93
+ basename = os.path.basename(target)
94
+ # cli-20260704_031310.log -> 20260704_031310
95
+ match = re.search(r"cli-(\d{8}_\d{6})\.log", basename)
96
+ if match:
97
+ dt_str = match.group(1)
98
+ except Exception:
99
+ pass
100
+
101
+ if not dt_str:
102
+ dt_str = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
103
+
104
+ log_dir = os.path.join(cwd, ".agents_brain", ".system_generated", dt_str, "logs")
105
+ os.makedirs(log_dir, exist_ok=True)
106
+ return log_dir
107
+
108
+ def log_to_brain(cwd: str, message: str):
109
+ """
110
+ 向当前会话的系统生成日志目录中写入调试日志。
111
+ """
112
+ try:
113
+ log_dir = resolve_log_dir(cwd)
114
+ log_file = os.path.join(log_dir, "hook_debug.log")
115
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
116
+ with open(log_file, "a", encoding="utf-8") as lf:
117
+ lf.write(f"[{timestamp}] {message}\n")
118
+ except Exception as e:
119
+ sys.stderr.write(f"Failed to write log to brain: {e}\n")