@ia-ccun/code-agent-cli 0.0.52 → 0.0.53-beta.2
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/bin/cli.js +97 -69
- package/config/agent/bin/README.md +102 -0
- package/config/agent/extensions/aicode-advisor.ts +197 -61
- package/config/agent/extensions/aicode-banner.ts +101 -0
- package/config/agent/extensions/aicode-btw.ts +677 -183
- package/config/agent/extensions/aicode-cd.ts +1017 -0
- package/config/agent/extensions/aicode-grillMe.ts +198 -0
- package/config/agent/extensions/aicode-pets.ts +351 -0
- package/config/agent/extensions/aicode-plan.ts +2 -0
- package/config/agent/extensions/aicode-safety-guard.ts +555 -0
- package/config/agent/extensions/aicode-tips.ts +69 -30
- package/config/agent/extensions/aicode-todo-progress.ts +547 -0
- package/config/agent/extensions/context-monitor.ts +30 -15
- package/config/agent/extensions/context.ts +132 -60
- package/config/agent/extensions/custom-footer.ts +0 -5
- package/config/agent/extensions/custom.ts +119 -109
- package/config/agent/extensions/error-monitor.ts +38 -51
- package/config/agent/extensions/goal.ts +8 -6
- package/config/agent/extensions/msg-debug.ts +103 -112
- package/config/agent/extensions/ponytail.ts +441 -0
- package/config/agent/extensions/review.ts +365 -164
- package/config/agent/extensions/tps.ts +87 -0
- package/config/agent/extensions/working-msg.ts +164 -51
- package/config/agent/help.md +0 -7
- package/config/agent/models.json +7 -7
- package/config/agent/settings.json +2 -1
- package/config/agent/skills/chroma/LICENSE +21 -0
- package/config/agent/skills/chroma/chroma-local/SKILL.md +165 -0
- package/config/agent/skills/chroma/chroma-local/cli.md +48 -0
- package/config/agent/skills/chroma/chroma-local/data-model.md +103 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/python.md +166 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/typescript.md +231 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/python.md +95 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/typescript.md +101 -0
- package/config/agent/skills/chroma/chroma-local/metadata/python.md +154 -0
- package/config/agent/skills/chroma/chroma-local/metadata/typescript.md +153 -0
- package/config/agent/skills/chroma/chroma-local/querying/python.md +147 -0
- package/config/agent/skills/chroma/chroma-local/querying/typescript.md +157 -0
- package/config/agent/skills/chroma/chroma-local/regex/python.md +69 -0
- package/config/agent/skills/chroma/chroma-local/regex/typescript.md +71 -0
- package/config/agent/skills/chroma/chroma-local/understanding-a-codebase.md +80 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/python.md +159 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/typescript.md +228 -0
- package/config/agent/skills/milvus-skill/LICENSE +202 -0
- package/config/agent/skills/milvus-skill/README.md +37 -0
- package/config/agent/skills/milvus-skill/SKILL.md +259 -0
- package/config/agent/skills/milvus-skill/references/collection.md +86 -0
- package/config/agent/skills/milvus-skill/references/database.md +24 -0
- package/config/agent/skills/milvus-skill/references/index.md +69 -0
- package/config/agent/skills/milvus-skill/references/partition.md +29 -0
- package/config/agent/skills/milvus-skill/references/patterns.md +150 -0
- package/config/agent/skills/milvus-skill/references/user-role.md +90 -0
- package/config/agent/skills/milvus-skill/references/vector.md +247 -0
- package/config/agent/skills/ponytail/SKILL.md +100 -0
- package/config/agent/skills/ponytail-audit/SKILL.md +40 -0
- package/config/agent/skills/ponytail-debt/SKILL.md +44 -0
- package/config/agent/skills/ponytail-help/SKILL.md +68 -0
- package/config/agent/skills/ponytail-review/SKILL.md +56 -0
- package/config/agent/skills/zread/README.md +115 -0
- package/config/agent/skills/zread/SKILL.md +103 -0
- package/config/agent/skills/zread/references/stdio-protocol.md +312 -0
- package/dist/banner.d.ts.map +1 -1
- package/dist/banner.js +8 -1
- package/dist/banner.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +9 -2
- package/dist/config-loader.js.map +1 -1
- package/package.json +7 -7
- package/scripts/postinstall.js +58 -1
- package/scripts/regression/README.md +224 -0
- package/scripts/regression/cases/01-version-and-deps.sh +94 -0
- package/scripts/regression/cases/02-extension-loading.sh +130 -0
- package/scripts/regression/cases/03-rpc-protocol.sh +259 -0
- package/scripts/regression/cases/04-prompt-stream.sh +130 -0
- package/scripts/regression/cases/05-slash-commands-and-skills.sh +119 -0
- package/scripts/regression/cases/06-tool-execution.sh +115 -0
- package/scripts/regression/cases/07-pi-new-features.sh +141 -0
- package/scripts/regression/lib/common.sh +287 -0
- package/scripts/regression/results/.last_pid +1 -0
- package/scripts/regression/results/.last_workdir +1 -0
- package/scripts/regression/results/02-extension-loading.log +18 -0
- package/scripts/regression/results/03-prompt-stream.log +16 -0
- package/scripts/regression/results/03-rpc-protocol.log +27 -0
- package/scripts/regression/results/04-slash-commands-and-skills.log +11 -0
- package/scripts/regression/results/05-tool-execution.log +8 -0
- package/scripts/regression/results/06-pi-new-features.log +29 -0
- package/scripts/regression/run-all.sh +187 -0
- package/config/agent/dangerous-patterns.json +0 -106
- package/config/agent/extensions/bash-check.ts +0 -227
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# aicode-cli 回归测试套件
|
|
2
|
+
|
|
3
|
+
> 用于验证每次升级 pi 底层依赖后,aicode-cli 的功能完整性不受影响。
|
|
4
|
+
> 也可用于新 aicode 版本发布前的本地预检。
|
|
5
|
+
|
|
6
|
+
## 设计目标
|
|
7
|
+
|
|
8
|
+
| 维度 | 验证内容 |
|
|
9
|
+
|---|---|
|
|
10
|
+
| **版本对齐** | aicode 二进制版本 + 4 个 pi 依赖包主版本一致 |
|
|
11
|
+
| **aicode 特色功能** | 20 个自定义 TS 扩展全部加载,无冲突 / 无语法错误 |
|
|
12
|
+
| **RPC 协议兼容** ⭐ | AicodeRpcClient.kt 实际用到的 17 个 RPC 命令 + 7 个事件类型 + 字段 schema |
|
|
13
|
+
| **预置资产** | 5 个 Prompt + 21+ 个 Skill 全部通过 `get_commands` 注册 |
|
|
14
|
+
| **核心能力** | prompt → message_update 完整事件流、tool_execution 配对 |
|
|
15
|
+
| **pi 0.85 新功能** | `clear_queue` RPC、GPT-6 Astra、thinking 持久化、`usage.cacheWrite1h` |
|
|
16
|
+
|
|
17
|
+
> ⭐ **RPC 协议兼容** 是本套件的核心重点 — 任何 RPC 命令的字段格式变化都会在 case 03 失败。
|
|
18
|
+
|
|
19
|
+
## 快速开始
|
|
20
|
+
|
|
21
|
+
### 前置依赖
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
brew install jq
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 运行全部测试
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 默认(使用 PATH 中的 aicode,配置目录 ~/.aicode-cli)
|
|
31
|
+
./run-all.sh
|
|
32
|
+
|
|
33
|
+
# 指定 aicode 二进制(测试本地包)
|
|
34
|
+
AICODE_BIN=$(pwd)/bin/cli.js ./run-all.sh
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 只跑部分 case
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 只跑 RPC 兼容性(升级后必跑)
|
|
41
|
+
./run-all.sh --only 03
|
|
42
|
+
|
|
43
|
+
# 跑 RPC + 新功能验证(最小升级预检)
|
|
44
|
+
./run-all.sh --only 03,07
|
|
45
|
+
|
|
46
|
+
# 跑核心 4 个
|
|
47
|
+
./run-all.sh --only 01,02,03,07
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 单个 case 直接跑
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
./cases/01-version-and-deps.sh
|
|
54
|
+
./cases/02-extension-loading.sh
|
|
55
|
+
./cases/03-rpc-protocol.sh
|
|
56
|
+
./cases/04-prompt-stream.sh
|
|
57
|
+
./cases/05-slash-commands-and-skills.sh
|
|
58
|
+
./cases/06-tool-execution.sh
|
|
59
|
+
./cases/07-pi-new-features.sh
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Case 清单
|
|
63
|
+
|
|
64
|
+
| Case | 文件 | 主题 | 关键断言 |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| **01** | `01-version-and-deps.sh` | 版本与依赖 | `aicode -v` 格式合规 + 4 个 pi 包主版本匹配 |
|
|
67
|
+
| **02** | `02-extension-loading.sh` | aicode 扩展加载 | 启动无 `Failed to load`/`conflict`/`SyntaxError`;aicode-* 命令注册 |
|
|
68
|
+
| **03** ⭐ | `03-rpc-protocol.sh` | **RPC 协议兼容性矩阵** | 17 个 RPC 命令 + 7 个事件类型 + 字段 schema + stopReason 枚举值 |
|
|
69
|
+
| **04** | `04-prompt-stream.sh` | prompt 事件流 | `agent_start`/`turn_start`/`message_update`(thinking_delta/text_delta)/`turn_end`/`agent_end` 序列 |
|
|
70
|
+
| **05** | `05-slash-commands-and-skills.sh` | Prompts + Skills | `/git-commit` `/workflow` 等 5 个 prompt + `/skill:code-review` 等核心 skill |
|
|
71
|
+
| **06** | `06-tool-execution.sh` | 工具调用 | `tool_execution_start` 必带 `toolCallId`+`toolName`(0.84.3 修复点) |
|
|
72
|
+
| **07** | `07-pi-new-features.sh` | pi 0.85 新功能 | `clear_queue` RPC、GPT-6、thinking 持久化、`cacheWrite1h` |
|
|
73
|
+
|
|
74
|
+
## RPC 协议覆盖矩阵(case 03)
|
|
75
|
+
|
|
76
|
+
### RPC 命令(17 个)
|
|
77
|
+
|
|
78
|
+
| 命令 | 来源 | 用途 |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `prompt` / `steer` / `follow_up` / `abort` | AicodeRpcClient.streamPrompt/Steer/FollowUp/abort | 消息流 |
|
|
81
|
+
| `compact` | AicodeRpcClient.compact | 上下文压缩 |
|
|
82
|
+
| `extension_ui_response` | AicodeRpcClient.respondExtensionUi | 扩展 UI 回调 |
|
|
83
|
+
| `get_state` / `get_session_stats` / `get_commands` | fetchState/fetchSessionStats/getCommands | 状态查询 |
|
|
84
|
+
| `get_available_models` / `get_available_thinking_levels` | AicodeRpcClient | 模型/thinking 选择 |
|
|
85
|
+
| `get_messages` / `get_entries` / `get_tree` | AicodeRpcClient | 会话历史 |
|
|
86
|
+
| `set_thinking_level` / `cycle_thinking_level` / `set_model_provider` | AicodeRpcClient | 模型控制 |
|
|
87
|
+
| `set_tools` | AicodeRpcClient.setTools | 工具开关 |
|
|
88
|
+
| `new_session` / `clear_queue` | AicodeRpcClient.newSession/clearQueue | 会话管理 + 队列 |
|
|
89
|
+
|
|
90
|
+
### 事件类型(11 个)
|
|
91
|
+
|
|
92
|
+
| 事件 | AicodeStreamItem 映射 |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `agent_start` / `turn_start` | lifecycle |
|
|
95
|
+
| `message_start` / `message_end` | lifecycle |
|
|
96
|
+
| `message_update` | Text / Thinking |
|
|
97
|
+
| `turn_end` / `agent_end` | TurnEnd / lifecycle |
|
|
98
|
+
| `tool_execution_start` / `_update` / `_end` | ToolStart / ToolUpdate / ToolEnd |
|
|
99
|
+
| `queue_update` | QueueUpdate |
|
|
100
|
+
| `auto_retry_end` | Error |
|
|
101
|
+
|
|
102
|
+
### 字段 schema(关键)
|
|
103
|
+
|
|
104
|
+
- `message_start.message.role` ∈ {user, assistant, toolResult}
|
|
105
|
+
- `message_update.assistantMessageEvent.{type, delta, contentIndex}`
|
|
106
|
+
- `turn_end.message.usage.{input, output, cost, ...}`
|
|
107
|
+
- `tool_execution_start.{toolCallId, toolName, args}` (0.84.3 修复点)
|
|
108
|
+
- `tool_execution_end.{isError: "true"|"false"}`
|
|
109
|
+
- `message_end.message.stopReason` ∈ {end_turn, tool_use, error, max_tokens, aborted}
|
|
110
|
+
- `agent_end.willRetry` ∈ {"true", "false"}
|
|
111
|
+
|
|
112
|
+
## 升级后必跑
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# 1. 改完 package.json,npm install
|
|
116
|
+
# 2. 编译
|
|
117
|
+
npm run build
|
|
118
|
+
|
|
119
|
+
# 3. RPC 兼容性是首要重点
|
|
120
|
+
./scripts/regression/run-all.sh --only 03
|
|
121
|
+
|
|
122
|
+
# 4. 全量回归
|
|
123
|
+
./scripts/regression/run-all.sh
|
|
124
|
+
|
|
125
|
+
# 5. 看 results/*.log
|
|
126
|
+
ls scripts/regression/results/
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 验收标准
|
|
130
|
+
|
|
131
|
+
升级可发布的最低条件:
|
|
132
|
+
|
|
133
|
+
| Case | 最低要求 |
|
|
134
|
+
|---|---|
|
|
135
|
+
| 01 version-and-deps | 全部 pass |
|
|
136
|
+
| 02 extension-loading | fail_count = 0 |
|
|
137
|
+
| **03 rpc-protocol** | **全部 pass 或 skip(已知不支持)** |
|
|
138
|
+
| 04 prompt-stream | 全部 pass |
|
|
139
|
+
| 05 slash-commands-and-skills | 注册率 ≥ 80% |
|
|
140
|
+
| 06 tool-execution | 至少 1 个 tool 事件配对成功 |
|
|
141
|
+
| 07 pi-new-features | skip 都标 "pi < 0.85.0 不支持" |
|
|
142
|
+
|
|
143
|
+
## 输出位置
|
|
144
|
+
|
|
145
|
+
| 文件 | 内容 |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `results/<case-name>.log` | 每个 case 的 stdout(pass/fail 行 + RPC 事件 log) |
|
|
148
|
+
| `results/.last_pid` | 最近一次 spawn 的 RPC 进程 PID(调试用) |
|
|
149
|
+
|
|
150
|
+
## 隔离机制
|
|
151
|
+
|
|
152
|
+
每个 case 独立 spawn 一个 `aicode --mode rpc --no-session` 子进程,使用临时目录(`mktemp -d`)作为 configDir,**不污染**用户 `~/.aicode-cli/`。结束后自动清理。
|
|
153
|
+
|
|
154
|
+
但 `02-extension-loading.sh` 需要真实加载扩展(不能用 `-ne`),所以它会用临时目录作为 configDir 跑全量加载,验证 20 个扩展都能正常启动。
|
|
155
|
+
|
|
156
|
+
## 依赖扩展的 case
|
|
157
|
+
|
|
158
|
+
- **02、05** 都需要正常启动扩展 → 不传 `-ne`
|
|
159
|
+
- **03、04、06、07** 主要测 RPC 协议 → 用 `-ne` 跳过扩展避免冲突
|
|
160
|
+
|
|
161
|
+
## 调试
|
|
162
|
+
|
|
163
|
+
### 单独看 RPC 事件流
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# 看 03 的 RPC 命令响应
|
|
167
|
+
jq -c 'select(.type=="response")' scripts/regression/results/03-rpc-protocol.log | head -20
|
|
168
|
+
|
|
169
|
+
# 看 message_update delta 流
|
|
170
|
+
grep message_update scripts/regression/results/04-prompt-stream.log | \
|
|
171
|
+
jq -c '{event: .assistantMessageEvent.type, delta: .assistantMessageEvent.delta}'
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 验证 RPC schema 漂移
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# 列出所有 turn_end 的 usage keys
|
|
178
|
+
jq -c 'select(.type=="turn_end") | .message.usage | keys | sort' \
|
|
179
|
+
scripts/regression/results/03-rpc-protocol.log | sort -u
|
|
180
|
+
|
|
181
|
+
# 对比不同 pi 版本
|
|
182
|
+
diff <(jq -c '...' results-v0.80.log) <(jq -c '...' results-v0.85.log)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 与 aicode-plugin-swing 的关系
|
|
186
|
+
|
|
187
|
+
| 层 | 测试位置 |
|
|
188
|
+
|---|---|
|
|
189
|
+
| aicode CLI 功能(命令/扩展/skills) | 本套件(scripts/regression/) |
|
|
190
|
+
| RPC 协议兼容性 | 本套件 case 03 ⭐ |
|
|
191
|
+
| Kotlin 客户端逻辑 | `~/icode/aicode-idea-plugin-swing/src/test/kotlin/com/nu/aicode/rpc/` |
|
|
192
|
+
| 升级兼容性评估 | `~/icode/aicode-idea-plugin-swing/docs/spec/upgrade-code-agent-cli-to-pi-085.md` |
|
|
193
|
+
| 端到端 IDE 集成 | aicode-plugin-swing 实际 IDE 测试 |
|
|
194
|
+
|
|
195
|
+
**本套件(CLI 侧)+ Kotlin 单元测试 + 实际 IDE 集成 = 完整回归链路。**
|
|
196
|
+
|
|
197
|
+
## 添加新 case
|
|
198
|
+
|
|
199
|
+
1. 复制 `cases/06-tool-execution.sh` → `cases/08-my-feature.sh`
|
|
200
|
+
2. 修改 `CURRENT_CASE`
|
|
201
|
+
3. 调用 `source "$SCRIPT_DIR/../lib/common.sh"`
|
|
202
|
+
4. 用 `pass` / `fail` / `skip` 报告结果
|
|
203
|
+
5. 最后 `summary; exit $?`
|
|
204
|
+
|
|
205
|
+
## 添加新的 RPC 命令到 case 03
|
|
206
|
+
|
|
207
|
+
编辑 `03-rpc-protocol.sh` 的 `RPC_COMMANDS` 数组:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
RPC_COMMANDS=(
|
|
211
|
+
...
|
|
212
|
+
"my_new_command|{\"foo\":\"bar\"}"
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
格式:`type|payload`,payload 会拼到 `{...,"id":"rpcN"}` 中。
|
|
217
|
+
|
|
218
|
+
## 修订记录
|
|
219
|
+
|
|
220
|
+
| 日期 | 修订 |
|
|
221
|
+
|---|---|
|
|
222
|
+
| 2026-09-12 | 初版:6 个 case |
|
|
223
|
+
| 2026-09-12 v2 | 新增 case 03 RPC 协议兼容性矩阵(17 命令 + 11 事件 + schema)|
|
|
224
|
+
| 2026-09-12 v2 | 重新编号:03 RPC / 04 prompt / 05 slash / 06 tool / 07 pi-new |
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 01-version-and-deps.sh
|
|
3
|
+
# 验证:aicode 二进制版本 + 内嵌 pi 包版本
|
|
4
|
+
# 这是回归测试的入口,确认我们用的版本符合预期
|
|
5
|
+
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
CURRENT_CASE="01-version-and-deps"
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
source "$SCRIPT_DIR/../lib/common.sh"
|
|
10
|
+
|
|
11
|
+
header "$CURRENT_CASE" "version & pi dependencies"
|
|
12
|
+
|
|
13
|
+
# ----- Test 1: aicode -v 输出 -----
|
|
14
|
+
header "$CURRENT_CASE" "aicode binary"
|
|
15
|
+
if ! command -v "$AICODE_BIN" >/dev/null 2>&1; then
|
|
16
|
+
fail "aicode 二进制存在" "未找到 $AICODE_BIN,设 AICODE_BIN 环境变量"
|
|
17
|
+
summary
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
pass "aicode 二进制存在 ($AICODE_BIN)"
|
|
21
|
+
|
|
22
|
+
VERSION=$("$AICODE_BIN" -v 2>&1 | head -1)
|
|
23
|
+
echo " version: $VERSION"
|
|
24
|
+
|
|
25
|
+
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9.]+)?$ ]]; then
|
|
26
|
+
pass "版本号格式合规 ($VERSION)"
|
|
27
|
+
else
|
|
28
|
+
fail "版本号格式合规" "got: $VERSION"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# ----- Test 2: 内嵌 pi 包版本 -----
|
|
32
|
+
header "$CURRENT_CASE" "pi package dependencies"
|
|
33
|
+
|
|
34
|
+
# 找到 aicode 安装路径里的 package.json
|
|
35
|
+
AICODE_PATH=$(command -v "$AICODE_BIN")
|
|
36
|
+
# 解析 symlink
|
|
37
|
+
if [[ -L "$AICODE_PATH" ]]; then
|
|
38
|
+
AICODE_PATH=$(readlink "$AICODE_PATH")
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# 找 package.json
|
|
42
|
+
RESOLVED_PATH=$(node -e "
|
|
43
|
+
const path = require('path');
|
|
44
|
+
const fs = require('fs');
|
|
45
|
+
let p = '$AICODE_PATH';
|
|
46
|
+
// aicode -> ../lib/node_modules/@ia-ccun/code-agent-cli/bin/cli.js
|
|
47
|
+
if (p.includes('/lib/node_modules/')) {
|
|
48
|
+
p = p.split('/lib/node_modules/')[0] + '/lib/node_modules/@ia-ccun/code-agent-cli';
|
|
49
|
+
} else if (p.includes('/.bin/')) {
|
|
50
|
+
p = path.join(path.dirname(p), '..', 'lib', 'node_modules', '@ia-ccun', 'code-agent-cli');
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(p, 'package.json'), 'utf8'));
|
|
54
|
+
console.log(p);
|
|
55
|
+
console.log(JSON.stringify(pkg.dependencies || {}));
|
|
56
|
+
} catch (e) { console.error(e.message); process.exit(1); }
|
|
57
|
+
" 2>&1) || {
|
|
58
|
+
fail "解析 aicode 安装路径" "node 解析失败"
|
|
59
|
+
summary
|
|
60
|
+
exit 1
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
AICODE_ROOT=$(echo "$RESOLVED_PATH" | head -1)
|
|
64
|
+
DEPS_JSON=$(echo "$RESOLVED_PATH" | tail -1)
|
|
65
|
+
echo " install path: $AICODE_ROOT"
|
|
66
|
+
echo " declared deps: $DEPS_JSON"
|
|
67
|
+
|
|
68
|
+
# 检查 4 个核心 pi 包
|
|
69
|
+
for pkg in @earendil-works/pi-agent-core @earendil-works/pi-ai @earendil-works/pi-coding-agent @earendil-works/pi-tui; do
|
|
70
|
+
declared=$(echo "$DEPS_JSON" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('$pkg','MISSING'))" 2>/dev/null)
|
|
71
|
+
if [[ "$declared" == "MISSING" || -z "$declared" ]]; then
|
|
72
|
+
fail "$pkg 已在 dependencies 声明" "declared: $declared"
|
|
73
|
+
continue
|
|
74
|
+
fi
|
|
75
|
+
pass "$pkg declared as $declared"
|
|
76
|
+
|
|
77
|
+
# 检查实际安装版本
|
|
78
|
+
actual=$("$AICODE_ROOT/node_modules/$pkg/package.json" -e "console.log(require('$AICODE_ROOT/node_modules/$pkg/package.json').version)" 2>/dev/null)
|
|
79
|
+
if [[ -n "$actual" ]]; then
|
|
80
|
+
# 解析 semver 主要版本
|
|
81
|
+
declared_major=$(echo "$declared" | sed -E 's/^[^0-9]*([0-9]+).*/\1/')
|
|
82
|
+
actual_major=$(echo "$actual" | sed -E 's/^[^0-9]*([0-9]+).*/\1/')
|
|
83
|
+
if [[ "$declared_major" == "$actual_major" ]]; then
|
|
84
|
+
pass "$pkg 安装版本 $actual 满足 ^$declared_major"
|
|
85
|
+
else
|
|
86
|
+
fail "$pkg 主版本一致" "declared major=$declared_major | actual=$actual"
|
|
87
|
+
fi
|
|
88
|
+
else
|
|
89
|
+
fail "$pkg 实际安装版本" "无法读取 $AICODE_ROOT/node_modules/$pkg/package.json"
|
|
90
|
+
fi
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
summary
|
|
94
|
+
exit $?
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 02-extension-loading.sh
|
|
3
|
+
# 验证:aicode-cli 自带的 20 个 TypeScript 扩展在 RPC 启动时全部成功加载
|
|
4
|
+
#
|
|
5
|
+
# 这是 aicode-cli 的核心差异化能力:
|
|
6
|
+
# - aicode-btw / aicode-plan / aicode-advisor / aicode-cd / aicode-grillMe
|
|
7
|
+
# - aicode-safety-guard / aicode-todo-progress / aicode-tips / aicode-pets
|
|
8
|
+
# - context-monitor / context / error-monitor / working-msg / tps
|
|
9
|
+
# - goal / review / ponytail / custom / custom-footer / msg-debug
|
|
10
|
+
#
|
|
11
|
+
# 升级 pi 后扩展 API 可能微调,必须验证:
|
|
12
|
+
# 1. 启动时没有任何 "Failed to load extension" 错误
|
|
13
|
+
# 2. 没有任何工具名冲突(conflict error)
|
|
14
|
+
# 3. 至少 N 个 aicode-* 扩展在 .agents.md 或 get_commands 中可见
|
|
15
|
+
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
CURRENT_CASE="02-extension-loading"
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
source "$SCRIPT_DIR/../lib/common.sh"
|
|
20
|
+
|
|
21
|
+
header "$CURRENT_CASE" "aicode custom extensions"
|
|
22
|
+
|
|
23
|
+
if ! spawn_rpc; then
|
|
24
|
+
fail "spawn aicode RPC(带扩展)" "进程启动失败"
|
|
25
|
+
summary
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
pass "spawn aicode RPC (pid=$REGRESSION_PID)"
|
|
29
|
+
|
|
30
|
+
# ----- Test 1: 启动日志中无扩展加载失败 -----
|
|
31
|
+
header "$CURRENT_CASE" "extension load errors"
|
|
32
|
+
|
|
33
|
+
# 把 stderr/stdout 全捕获到 log(-ne 关闭扩展 → 我们用普通模式)
|
|
34
|
+
cleanup_rpc
|
|
35
|
+
|
|
36
|
+
# 重启:不用 -ne,让所有扩展都加载
|
|
37
|
+
WORKDIR=$(mktemp -d -t aicode-ext.XXXXXX)
|
|
38
|
+
cat >"$WORKDIR/config.json" <<EOF
|
|
39
|
+
{"name":"aicode-test","banner":"","themeColor":"#49bccf","configDir":"$(basename "$WORKDIR")"}
|
|
40
|
+
EOF
|
|
41
|
+
|
|
42
|
+
LOG="$RESULTS_DIR/${CURRENT_CASE}.log"
|
|
43
|
+
: >"$LOG"
|
|
44
|
+
|
|
45
|
+
"$AICODE_BIN" --config "$WORKDIR" --mode rpc --no-session \
|
|
46
|
+
< /dev/null >"$LOG" 2>&1 &
|
|
47
|
+
EXT_PID=$!
|
|
48
|
+
|
|
49
|
+
# 等启动完成(5s 应该够)
|
|
50
|
+
sleep 5
|
|
51
|
+
kill "$EXT_PID" 2>/dev/null
|
|
52
|
+
wait "$EXT_PID" 2>/dev/null
|
|
53
|
+
|
|
54
|
+
# 错误关键字扫描
|
|
55
|
+
echo " scanning log for extension errors..."
|
|
56
|
+
|
|
57
|
+
fail_count=0
|
|
58
|
+
for pattern in "Failed to load extension" "Tool.*conflicts with" "Cannot find module" "SyntaxError" "TypeError.*Extension"; do
|
|
59
|
+
matches=$(grep -cE "$pattern" "$LOG" 2>/dev/null || echo 0)
|
|
60
|
+
if [[ "$matches" -gt 0 ]]; then
|
|
61
|
+
fail "无 $pattern 错误" "found $matches matches"
|
|
62
|
+
grep -E "$pattern" "$LOG" | head -3 | sed 's/^/ /'
|
|
63
|
+
fail_count=$((fail_count + matches))
|
|
64
|
+
else
|
|
65
|
+
pass "无 '$pattern' 错误"
|
|
66
|
+
fi
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
# ----- Test 2: get_commands 包含 aicode- 自定义命令 -----
|
|
70
|
+
# 不带 -ne 启动,确认扩展注册的 slash commands 也可见
|
|
71
|
+
header "$CURRENT_CASE" "aicode custom slash commands"
|
|
72
|
+
|
|
73
|
+
spawn_rpc 2>/dev/null || {
|
|
74
|
+
fail "second spawn" "进程启动失败"
|
|
75
|
+
summary; exit 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
send '{"type":"get_commands","id":"e1"}'
|
|
79
|
+
sleep 1
|
|
80
|
+
|
|
81
|
+
cmds_json=$(jq -c 'select(.id=="e1" and .type=="response") | .data.commands' "$REGRESSION_LOG" 2>/dev/null | head -1)
|
|
82
|
+
cmd_count=$(echo "$cmds_json" | jq -c 'length' 2>/dev/null)
|
|
83
|
+
echo " registered commands: $cmd_count"
|
|
84
|
+
|
|
85
|
+
if [[ -z "$cmd_count" || "$cmd_count" == "null" || "$cmd_count" -lt 5 ]]; then
|
|
86
|
+
fail "至少注册 5 个命令" "got: $cmd_count"
|
|
87
|
+
else
|
|
88
|
+
pass "注册 $cmd_count 个 slash commands"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# 关键 aicode 自定义命令(在 /llama /model /settings 等内置之外的 aicode-*)
|
|
92
|
+
AICODE_CMDS=("/aicode-cd" "/grill-me" "/bugs" "/goal" "/plan" "/workflow" "/git-commit" "/feat" "/init-project" "/code-simplifier")
|
|
93
|
+
for cmd in "${AICODE_CMDS[@]}"; do
|
|
94
|
+
if echo "$cmds_json" | jq -e --arg c "$cmd" '.[] | select(.name == $c)' >/dev/null 2>&1; then
|
|
95
|
+
pass "扩展命令 $cmd 已注册"
|
|
96
|
+
else
|
|
97
|
+
# 可能该命令需要其他条件才注册,标记 skip
|
|
98
|
+
skip "扩展命令 $cmd 已注册" "未在 get_commands 中找到"
|
|
99
|
+
fi
|
|
100
|
+
done
|
|
101
|
+
|
|
102
|
+
# ----- Test 3: get_state 反映扩展注册的工具 -----
|
|
103
|
+
header "$CURRENT_CASE" "tools registered by extensions"
|
|
104
|
+
|
|
105
|
+
send '{"type":"get_state","id":"e2"}'
|
|
106
|
+
sleep 1
|
|
107
|
+
|
|
108
|
+
# 通过发 prompt 让模型思考,看 tool_execution_start 是否包含 aicode 扩展工具
|
|
109
|
+
# (aicode-safety-guard 注册的 safety_check / aicode-plan 注册的 todo_update 等)
|
|
110
|
+
|
|
111
|
+
send '{"type":"prompt","message":"just say hi","id":"e3"}'
|
|
112
|
+
sleep 8
|
|
113
|
+
|
|
114
|
+
# 收集所有出现过的 tool_name
|
|
115
|
+
all_tools=$(jq -r 'select(.type=="tool_execution_start") | .toolName // empty' "$REGRESSION_LOG" 2>/dev/null | sort -u)
|
|
116
|
+
echo " observed tools: $(echo "$all_tools" | tr '\n' ' ')"
|
|
117
|
+
|
|
118
|
+
# 内置工具一定在
|
|
119
|
+
for tool in read bash write edit; do
|
|
120
|
+
if echo "$all_tools" | grep -qx "$tool"; then
|
|
121
|
+
pass "内置工具 $tool 可调用"
|
|
122
|
+
else
|
|
123
|
+
# 单次 prompt 可能不调用
|
|
124
|
+
skip "内置工具 $tool 可调用" "本次 prompt 未触发"
|
|
125
|
+
fi
|
|
126
|
+
done
|
|
127
|
+
|
|
128
|
+
cleanup_rpc
|
|
129
|
+
summary
|
|
130
|
+
exit $?
|