@qwen-code/arena-agent 0.0.9-dev.2 → 0.0.9-dev.21
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/.env.example +41 -2
- package/README.md +145 -16
- package/dist/agent.d.ts +3 -1
- package/dist/agent.js +61 -15
- package/dist/agent.js.map +1 -1
- package/dist/anthropic.js +3 -1
- package/dist/anthropic.js.map +1 -1
- package/dist/ask-user.d.ts +20 -0
- package/dist/ask-user.js +388 -0
- package/dist/ask-user.js.map +1 -0
- package/dist/attachments.d.ts +1 -1
- package/dist/attachments.js +16 -4
- package/dist/attachments.js.map +1 -1
- package/dist/brave-search.d.ts +6 -0
- package/dist/brave-search.js +193 -0
- package/dist/brave-search.js.map +1 -0
- package/dist/canonical-data.d.ts +1 -0
- package/dist/canonical-data.js +1 -0
- package/dist/canonical-data.js.map +1 -1
- package/dist/cli.js +43 -11
- package/dist/cli.js.map +1 -1
- package/dist/code-cli.d.ts +2 -0
- package/dist/code-cli.js +12 -0
- package/dist/code-cli.js.map +1 -0
- package/dist/code-tools.d.ts +68 -0
- package/dist/code-tools.js +1925 -0
- package/dist/code-tools.js.map +1 -0
- package/dist/config.d.ts +12 -1
- package/dist/config.js +51 -3
- package/dist/config.js.map +1 -1
- package/dist/document-reader.js +9 -0
- package/dist/document-reader.js.map +1 -1
- package/dist/fetch-page.d.ts +3 -0
- package/dist/fetch-page.js +51 -22
- package/dist/fetch-page.js.map +1 -1
- package/dist/history.d.ts +2 -0
- package/dist/history.js +1 -0
- package/dist/history.js.map +1 -1
- package/dist/image.d.ts +14 -0
- package/dist/image.js +299 -0
- package/dist/image.js.map +1 -0
- package/dist/mock.d.ts +1 -0
- package/dist/mock.js +38 -0
- package/dist/mock.js.map +1 -1
- package/dist/mode.d.ts +6 -0
- package/dist/mode.js +33 -0
- package/dist/mode.js.map +1 -0
- package/dist/model-diagnostics.js +5 -2
- package/dist/model-diagnostics.js.map +1 -1
- package/dist/provider.js +14 -5
- package/dist/provider.js.map +1 -1
- package/dist/routify-web-fetch.d.ts +17 -0
- package/dist/routify-web-fetch.js +188 -0
- package/dist/routify-web-fetch.js.map +1 -0
- package/dist/sdk.d.ts +35 -3
- package/dist/sdk.js +6 -2
- package/dist/sdk.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.js +86 -5
- package/dist/server.js.map +1 -1
- package/dist/spec.d.ts +11 -8
- package/dist/spec.js +105 -13
- package/dist/spec.js.map +1 -1
- package/dist/tools.d.ts +10 -27
- package/dist/tools.js +72 -60
- package/dist/tools.js.map +1 -1
- package/dist/tui.d.ts +3 -0
- package/dist/tui.js +11 -2
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +9 -2
- package/dist/web/app.d.ts +1 -0
- package/dist/web/app.js +59 -6
- package/dist/web/app.js.map +1 -1
- package/dist/workspace.d.ts +12 -0
- package/dist/workspace.js +165 -0
- package/dist/workspace.js.map +1 -0
- package/docs/BINARY_DISTRIBUTION.md +231 -0
- package/docs/MODES_AND_RELEASES.md +123 -0
- package/docs/SDK.md +24 -1
- package/modes/code-arena/full-stack/system-prompt.txt +77 -0
- package/modes/code-arena/full-stack/template/.env +1 -0
- package/modes/code-arena/full-stack/template/drizzle.config.json +7 -0
- package/modes/code-arena/full-stack/template/eslint.config.mjs +9 -0
- package/modes/code-arena/full-stack/template/next.config.ts +5 -0
- package/modes/code-arena/full-stack/template/package.json +32 -0
- package/modes/code-arena/full-stack/template/postcss.config.mjs +7 -0
- package/modes/code-arena/full-stack/template/src/app/api/health/route.ts +13 -0
- package/modes/code-arena/full-stack/template/src/app/globals.css +1 -0
- package/modes/code-arena/full-stack/template/src/app/layout.tsx +16 -0
- package/modes/code-arena/full-stack/template/src/app/page.tsx +22 -0
- package/modes/code-arena/full-stack/template/src/db/index.ts +24 -0
- package/modes/code-arena/full-stack/template/src/db/schema.ts +3 -0
- package/modes/code-arena/full-stack/template/tsconfig.json +24 -0
- package/modes/code-arena/full-stack/tools.json +446 -0
- package/modes/code-arena/html/system-prompt.txt +36 -0
- package/modes/code-arena/html/tools.json +284 -0
- package/modes/code-arena/model.json +10 -0
- package/modes/code-arena/react/system-prompt.txt +33 -0
- package/modes/code-arena/react/template/index.html +12 -0
- package/modes/code-arena/react/template/package.json +28 -0
- package/modes/code-arena/react/template/src/App.tsx +28 -0
- package/modes/code-arena/react/template/src/index.css +1 -0
- package/modes/code-arena/react/template/src/main.tsx +10 -0
- package/modes/code-arena/react/template/src/utils/cn.ts +6 -0
- package/modes/code-arena/react/template/tsconfig.json +25 -0
- package/modes/code-arena/react/template/vite.config.ts +18 -0
- package/modes/code-arena/react/tools.json +410 -0
- package/package.json +33 -5
- package/web/styles.css +22 -7
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Arena 多平台单文件二进制
|
|
2
|
+
|
|
3
|
+
Arena 可以使用 Node.js Single Executable Applications(SEA)构建为一个包含
|
|
4
|
+
Node.js 运行时、应用代码和静态资源的可执行文件。目标机器不需要安装 Node.js。
|
|
5
|
+
|
|
6
|
+
如果业务机只是受安装权限或 Node.js 版本管理限制,这种方式可以绕过安装步骤。
|
|
7
|
+
Linux x64 glibc 包固定使用 Node.js unofficial-builds 的 glibc 2.17 Runtime,支持
|
|
8
|
+
CentOS 7 / glibc 2.17 及更新的 glibc 系统;低于 glibc 2.17 的系统仍无法运行。
|
|
9
|
+
|
|
10
|
+
## npm 安装(业务机有 Node.js 18)
|
|
11
|
+
|
|
12
|
+
推荐业务方安装统一入口包:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @qwen-code/arena-cli
|
|
16
|
+
arena --version
|
|
17
|
+
code-harness --version
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`@qwen-code/arena-cli` 是一个兼容 Node.js 18 的小型启动器。npm 会通过
|
|
21
|
+
`optionalDependencies` 安装当前系统对应的平台包,启动器检测操作系统、CPU 和
|
|
22
|
+
Linux libc 后运行其中的同一个 SEA 文件。`arena` 默认选择 Arena 模式,
|
|
23
|
+
`code-harness` 默认选择 React 模式;二者都可用 `--mode` 选择四种模式。
|
|
24
|
+
Harness 本身使用 SEA 内嵌的 Node.js 运行时,
|
|
25
|
+
业务机不需要 Node.js 20+。
|
|
26
|
+
|
|
27
|
+
不要使用 `--omit=optional` 安装入口包;否则需要显式安装对应的平台包。
|
|
28
|
+
|
|
29
|
+
现有的 `@qwen-code/arena-agent` 继续提供 JavaScript CLI 和 SDK,并同时暴露
|
|
30
|
+
`arena`、`code-harness` 两个命令,仍要求 Node.js 20.16+。它与平台包是两种
|
|
31
|
+
分发形式,不是两套模式实现。
|
|
32
|
+
|
|
33
|
+
## 直接安装(业务机没有 Node.js)
|
|
34
|
+
|
|
35
|
+
npm 命令本身需要 Node.js。如果业务机连 Node.js 18 也没有,macOS/Linux 可以
|
|
36
|
+
直接安装最新稳定版:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
curl -fsSL https://cdn.jsdelivr.net/npm/@qwen-code/arena-cli@latest/install.sh | sh
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
跟随滚动更新的 dev 渠道并指定安装目录:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
curl -fsSL https://cdn.jsdelivr.net/npm/@qwen-code/arena-cli@dev/install.sh \
|
|
46
|
+
| sh -s -- --version dev --install-dir "$HOME/bin"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
这里的两个 `dev` 都需要保留:前者选择安装脚本,后者选择对应平台二进制。
|
|
50
|
+
|
|
51
|
+
安装脚本检测 macOS/Linux、x64/arm64 与 Linux glibc/musl,从 npm 下载对应平台包,
|
|
52
|
+
校验 tarball checksum,并把 `arena` 安装到 `~/.local/bin`。如果该目录不在 PATH,
|
|
53
|
+
脚本会幂等更新当前 shell 的 profile;设置 `ARENA_NO_MODIFY_PATH=1` 可以关闭。
|
|
54
|
+
|
|
55
|
+
也可以从平台包中取出 `bin/arena`(Windows 为 `bin/arena.exe`),直接复制运行。
|
|
56
|
+
|
|
57
|
+
macOS / Linux:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
chmod +x arena
|
|
61
|
+
./arena --version
|
|
62
|
+
./arena -p "分析当前项目"
|
|
63
|
+
./arena --mode full-stack -p "创建一个应用"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Windows:
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
.\arena.exe --version
|
|
70
|
+
.\arena.exe -p "分析当前项目"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
模型地址、密钥和其他配置仍通过 `.env` 或环境变量提供。
|
|
74
|
+
|
|
75
|
+
## npm 平台包矩阵
|
|
76
|
+
|
|
77
|
+
所有包必须使用与仓库根 `package.json` 完全相同的版本号。
|
|
78
|
+
|
|
79
|
+
| 目标 | npm 包 |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| macOS arm64 | `@qwen-code/arena-darwin-arm64` |
|
|
82
|
+
| macOS x64 | `@qwen-code/arena-darwin-x64` |
|
|
83
|
+
| Linux arm64 glibc | `@qwen-code/arena-linux-arm64` |
|
|
84
|
+
| Linux arm64 musl | `@qwen-code/arena-linux-arm64-musl` |
|
|
85
|
+
| Linux x64 glibc | `@qwen-code/arena-linux-x64` |
|
|
86
|
+
| Linux x64 musl | `@qwen-code/arena-linux-x64-musl` |
|
|
87
|
+
| Windows x64 | `@qwen-code/arena-win32-x64` |
|
|
88
|
+
|
|
89
|
+
Node SEA 使用 Node 官方运行时,不需要像部分 Bun 二进制那样再拆 AVX2 与 baseline。
|
|
90
|
+
如果以后引入有额外 CPU 指令要求的原生依赖,再扩展目标矩阵。
|
|
91
|
+
|
|
92
|
+
## 在各平台构建
|
|
93
|
+
|
|
94
|
+
构建机要求 Node.js 20.16+。面向旧业务系统的正式发布建议固定使用 Node.js 20.x,
|
|
95
|
+
不要因为构建 runner 自动升级而无意中嵌入 Node.js 22/24:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm ci
|
|
99
|
+
npm run package:binary
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
默认命令构建当前 runner 的系统、CPU 和 libc。CI 还支持在 Linux x64 上按 Node
|
|
103
|
+
SEA 跨平台流程生成三个关键目标:`linux-x64` 固定下载完全相同版本的 Node.js
|
|
104
|
+
unofficial-builds glibc 2.17 Runtime,`linux-x64-musl` 下载 unofficial-builds
|
|
105
|
+
musl Runtime,`darwin-x64` 下载官方 macOS x64 Runtime。三者都通过 Aone 可访问的
|
|
106
|
+
npmmirror 二进制镜像下载,并校验对应的
|
|
107
|
+
`SHASUMS256.txt`,关闭 code cache/snapshot 后注入 SEA blob。
|
|
108
|
+
macOS 产物再使用固定版本和 checksum 的 `rcodesign` 做 ad-hoc 签名。Aone 从仓库的
|
|
109
|
+
`toolchains/apple-codesign-0.29.0` 工具链分支拉取固定 commit,避免构建时依赖 GitHub
|
|
110
|
+
Release 的网络可用性;本地构建未指定 `ARENA_RCODESIGN_ARCHIVE` 时仍会从官方
|
|
111
|
+
Release 下载。产物包括:
|
|
112
|
+
|
|
113
|
+
- SEA 文件:macOS / Linux 为 `build/sea/arena`,Windows 为
|
|
114
|
+
`build/sea/arena.exe`
|
|
115
|
+
- 待发布包目录:`build/npm/packages/<target>` 与 `build/npm/packages/cli`
|
|
116
|
+
- npm tarball:`build/npm/tarballs/*.tgz`
|
|
117
|
+
|
|
118
|
+
`build/sea` 最终只保留需要交付的可执行文件。构建脚本会自动运行一次
|
|
119
|
+
`arena --version` 冒烟检查。
|
|
120
|
+
|
|
121
|
+
Code Arena 的 prompt/tool contract 会编译进 bundle;React 与 Full Stack
|
|
122
|
+
scaffold 会作为 SEA assets 一起嵌入。四种模式只构建一次,不为每个模式重复平台
|
|
123
|
+
矩阵。
|
|
124
|
+
|
|
125
|
+
如果已经有另一个 runner 产生的二进制,也可以只组装指定平台包:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
node scripts/package-binaries.mjs \
|
|
129
|
+
--target linux-x64 \
|
|
130
|
+
--binary artifacts/linux-x64/arena \
|
|
131
|
+
--skip-cli
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
CI 应构建并汇总 `build/npm/packages/<target>`。原生 Runtime 通常应在对应环境中
|
|
135
|
+
构建;禁用 SEA snapshot/code cache 后,`linux-x64`、`linux-x64-musl` 和
|
|
136
|
+
`darwin-x64` 都可以在 Linux x64 Runner 上使用经过校验的目标 Node Runtime
|
|
137
|
+
组装。
|
|
138
|
+
|
|
139
|
+
本仓库使用 Aone CI,流水线定义在
|
|
140
|
+
[`/.aoneci/arena-binaries.yaml`](../.aoneci/arena-binaries.yaml)。当前项目没有关联
|
|
141
|
+
自托管 Runner 组,因此流水线优先使用 Aone 托管的 Linux amd64 资源构建
|
|
142
|
+
`linux-x64`,并交叉构建 `linux-x64-musl` 和 `darwin-x64`。推送与根
|
|
143
|
+
`package.json` 版本完全一致的 `v<semver>` Tag 时会自动运行,并在同一批次
|
|
144
|
+
发布这三个关键平台包、`@qwen-code/arena-agent` 和
|
|
145
|
+
`@qwen-code/arena-cli`;后两个包都包含四种模式和两个命令入口。普通分支 push
|
|
146
|
+
不触发,手动运行只构建、不发布。发布前
|
|
147
|
+
需要在“设置 → 持续集成 → 变量管理”中添加名为 `NPM_TOKEN` 的 Secret。
|
|
148
|
+
|
|
149
|
+
例如,预发布版自动使用 npm `dev` tag:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm version 0.0.10-dev.1 --no-git-tag-version
|
|
153
|
+
git add package.json package-lock.json
|
|
154
|
+
git commit -m "chore: release 0.0.10-dev.1"
|
|
155
|
+
git push origin master
|
|
156
|
+
git tag v0.0.10-dev.1
|
|
157
|
+
git push origin v0.0.10-dev.1
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
正式版同理,例如 `package.json` 为 `0.0.10` 时推送 `v0.0.10`,发布脚本会自动
|
|
161
|
+
使用 npm `latest` tag。Tag 名与版本不一致时发布步骤会直接失败,避免把错误版本
|
|
162
|
+
发布到 npm。首次稳定版发布前请显式使用 `@dev` 或完整版本号;首个正式版本发布后
|
|
163
|
+
才把无版本安装渠道作为稳定入口。
|
|
164
|
+
|
|
165
|
+
Aone 官方不提供 Windows/macOS 托管资源;`darwin-x64` 已通过上述交叉构建覆盖。
|
|
166
|
+
Linux arm64 的两个平台包暂不参与自动发布,以免非关键 ARM64 Job 阻塞 x64
|
|
167
|
+
发布。发布 `darwin-arm64` 和 Windows 包前,仍需要关联对应的 self-hosted Runner
|
|
168
|
+
组。
|
|
169
|
+
|
|
170
|
+
## 发布
|
|
171
|
+
|
|
172
|
+
汇总全部 7 个平台包目录后,重新生成一次入口包并进行发布前检查:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm run package:binary:cli
|
|
176
|
+
npm run publish:binaries -- --dry-run --tag dev
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
确认后去掉 `--dry-run`,按需传入 registry:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
npm run publish:binaries -- \
|
|
183
|
+
--tag dev \
|
|
184
|
+
--registry https://registry.example.com
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
发布脚本会校验 7 个平台包和入口包的名称、版本、依赖是否一致,并严格依次发布
|
|
188
|
+
平台包、`@qwen-code/arena-agent`,最后发布 `@qwen-code/arena-cli`。失败后重跑会
|
|
189
|
+
跳过 npm 上已经存在的同版本包。预发布版本默认使用 `dev` tag,稳定版本默认使用
|
|
190
|
+
`latest` tag,也可以显式用 `--tag` 覆盖。
|
|
191
|
+
|
|
192
|
+
入口包必须最后发布;否则用户可能在平台包尚未可用时安装到一个缺少二进制的版本。
|
|
193
|
+
|
|
194
|
+
## 平台与兼容性
|
|
195
|
+
|
|
196
|
+
SEA 产物内含目标平台的 Node.js 可执行文件,因此需要为每种目标分别构建:
|
|
197
|
+
|
|
198
|
+
- macOS arm64 与 x64
|
|
199
|
+
- Linux arm64/x64 的 glibc 与 musl
|
|
200
|
+
- Windows x64
|
|
201
|
+
|
|
202
|
+
除流水线已覆盖的三个关键 x64 目标外,其他目标应在对应操作系统和 CPU 架构的
|
|
203
|
+
构建机或 CI runner 上执行。
|
|
204
|
+
|
|
205
|
+
“业务机不需要 Node.js 20+”不等于“二进制不受 Node.js 20 的系统要求影响”。
|
|
206
|
+
SEA 把 Node.js 可执行文件放进 Arena,运行时仍由操作系统加载这个内嵌运行时:
|
|
207
|
+
|
|
208
|
+
- 当前 Linux x64 glibc 包的最低要求是 glibc 2.17;
|
|
209
|
+
- musl 包用于 Alpine 等 musl 系统,不能代替 glibc 包;
|
|
210
|
+
- 在较新的 Linux 上打包,不能自动获得对更老 glibc 的兼容性。
|
|
211
|
+
|
|
212
|
+
因此,业务机只有 Node.js 18 通常不是问题;真正需要确认的是它的操作系统、CPU
|
|
213
|
+
架构和 `ldd --version`。Linux x64 的 glibc 2.17 兼容性来自构建脚本选择的
|
|
214
|
+
`linux-x64-glibc-217` Runtime,而不是构建 runner 的系统版本。如果业务机低于
|
|
215
|
+
glibc 2.17,仍必须使用更老系统兼容的 Runtime 重新制作平台包,或升级业务系统。
|
|
216
|
+
仅仅在“更老的 Docker 镜像”里复制同一个官方 Node.js 二进制并不能降低其 glibc
|
|
217
|
+
下限。
|
|
218
|
+
|
|
219
|
+
单文件只消除了目标机器安装 Node.js 的要求,并不会内嵌所有外部程序:
|
|
220
|
+
|
|
221
|
+
- `bash` 工具仍要求 `/bin/bash`。
|
|
222
|
+
- Git 仓库识别仍需要系统提供 `git`。
|
|
223
|
+
- 旧版 `.doc`、`.ppt`、`.xls` 转换仍需要 LibreOffice;现代 Office 文档和 PDF
|
|
224
|
+
读取已包含在二进制中。
|
|
225
|
+
|
|
226
|
+
macOS 构建会进行 ad-hoc 签名。对外分发时,建议在构建完成后使用正式开发者证书
|
|
227
|
+
重新签名并按组织要求完成 notarization。Windows 也可以在构建后使用组织证书签名。
|
|
228
|
+
|
|
229
|
+
实现基于 [Node.js SEA 官方文档](https://nodejs.org/api/single-executable-applications.html)、
|
|
230
|
+
[Node.js unofficial-builds](https://github.com/nodejs/unofficial-builds) 和
|
|
231
|
+
[rcodesign 文档](https://gregoryszorc.com/docs/apple-codesign/stable/)。
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# 四模式架构与发包方案
|
|
2
|
+
|
|
3
|
+
## 结论
|
|
4
|
+
|
|
5
|
+
本仓库采用“一个核心包、四种运行模式”,不改成 monorepo。
|
|
6
|
+
|
|
7
|
+
- `arena`、`react`、`html`、`full-stack` 共用当前仓库的配置、provider、
|
|
8
|
+
agent loop、compaction、history、metrics、CLI/TUI/server 和 SDK。
|
|
9
|
+
- 模式边界只包含 system prompt、工具 schema/实现以及可选 scaffold。
|
|
10
|
+
- 四种模式使用同一个版本号一起演进,避免两份 agent loop 再次漂移。
|
|
11
|
+
- JavaScript/SDK 包与 SEA 二进制包是两种分发形式,可以按需要分别发布;
|
|
12
|
+
它们不是两套产品源码,也不要求 npm workspaces。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
src/
|
|
18
|
+
agent.ts # 唯一 agent loop
|
|
19
|
+
config.ts # 唯一配置入口
|
|
20
|
+
tools.ts # mode-aware facade + Arena tools
|
|
21
|
+
code-tools.ts # 三种 Code Arena 工具语义
|
|
22
|
+
mode.ts # 四模式名称、别名与默认 step limit
|
|
23
|
+
workspace.ts # React/Full Stack scaffold 初始化
|
|
24
|
+
|
|
25
|
+
spec/ # Arena 生产 fixtures(保持原路径)
|
|
26
|
+
modes/code-arena/
|
|
27
|
+
model.json # 三种 Code Arena 共用模型参数
|
|
28
|
+
react/
|
|
29
|
+
system-prompt.txt
|
|
30
|
+
tools.json
|
|
31
|
+
template/
|
|
32
|
+
html/
|
|
33
|
+
system-prompt.txt
|
|
34
|
+
tools.json
|
|
35
|
+
full-stack/
|
|
36
|
+
system-prompt.txt
|
|
37
|
+
tools.json
|
|
38
|
+
template/
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`scripts/generate-canonical-data.mjs` 将 Arena fixtures 和三种 Code Arena
|
|
42
|
+
contract 一起编译到 `src/canonical-data.ts`。正常 npm 运行不读取 prompt/schema
|
|
43
|
+
源文件;scaffold 仍作为包资源保留,SEA 构建时则作为 assets 嵌入二进制。
|
|
44
|
+
|
|
45
|
+
## 模式选择
|
|
46
|
+
|
|
47
|
+
统一 CLI 使用显式参数:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
arena --mode arena -p '...'
|
|
51
|
+
arena --mode react -p '...'
|
|
52
|
+
arena --mode html -p '...'
|
|
53
|
+
arena --mode full-stack -p '...'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
兼容命令 `code-harness` 进入同一 CLI,缺省模式为 `react`。环境变量优先级为:
|
|
57
|
+
|
|
58
|
+
1. CLI `--mode`
|
|
59
|
+
2. `ARENA_HARNESS_MODE`
|
|
60
|
+
3. `CODE_HARNESS_MODE`(兼容)
|
|
61
|
+
4. `ARENA_MODE`(兼容)
|
|
62
|
+
5. `arena` 命令默认 `arena`;`code-harness` 命令默认 `react`
|
|
63
|
+
|
|
64
|
+
历史记录会保存 `mode`,system prompt 的 canonical 校验会阻止用错误模式续跑
|
|
65
|
+
同一轨迹。Code Arena 模式不启用 Arena 的自动 repo prompt;即使工作区位于 Git
|
|
66
|
+
仓库中,也仍使用所选的 Code Arena prompt。
|
|
67
|
+
|
|
68
|
+
## npm 与二进制
|
|
69
|
+
|
|
70
|
+
### JavaScript/SDK 包
|
|
71
|
+
|
|
72
|
+
`@qwen-code/arena-agent` 同时发布:
|
|
73
|
+
|
|
74
|
+
- `arena -> dist/cli.js`
|
|
75
|
+
- `code-harness -> dist/code-cli.js`
|
|
76
|
+
- SDK 的 Arena 名称与 Code Harness 兼容别名
|
|
77
|
+
- 四种模式所需的 scaffold
|
|
78
|
+
|
|
79
|
+
这是日常源码安装和 SDK 消费的发布单元,要求 Node.js 20.16+。
|
|
80
|
+
|
|
81
|
+
### 单文件二进制
|
|
82
|
+
|
|
83
|
+
`@qwen-code/arena-cli` 是兼容 Node.js 18 的平台选择器,同时提供 `arena` 和
|
|
84
|
+
`code-harness` 两个命令。它们启动同一个 SEA 文件;`code-harness` launcher
|
|
85
|
+
只负责注入默认 `react` 模式。平台包继续使用 `@qwen-code/arena-<platform>`
|
|
86
|
+
命名,无需为四种模式复制一套平台矩阵。
|
|
87
|
+
|
|
88
|
+
因此一次平台构建包含全部四种模式,版本和校验和天然一致。
|
|
89
|
+
|
|
90
|
+
## 发布节奏
|
|
91
|
+
|
|
92
|
+
可以只发布 JavaScript/SDK 包,也可以在随后完成 7 个平台的 SEA 包和 launcher;
|
|
93
|
+
但不建议单独发布某一个模式。推荐顺序:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run typecheck
|
|
97
|
+
npm test
|
|
98
|
+
npm pack --dry-run
|
|
99
|
+
|
|
100
|
+
# 每个平台 runner
|
|
101
|
+
npm run package:binary:platform
|
|
102
|
+
|
|
103
|
+
# 汇总平台产物后
|
|
104
|
+
npm run package:binary:cli
|
|
105
|
+
npm run publish:binaries -- --dry-run
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
平台包必须先于 `@qwen-code/arena-cli` 发布。完整矩阵见
|
|
109
|
+
[`BINARY_DISTRIBUTION.md`](BINARY_DISTRIBUTION.md)。
|
|
110
|
+
|
|
111
|
+
## 原 Code Harness 的迁移边界
|
|
112
|
+
|
|
113
|
+
迁入的是三种模式的运行时 contract、工具行为和 scaffold;没有迁入旧仓库中
|
|
114
|
+
已经落后的 agent loop、配置、server、SDK 或 Web UI 副本。
|
|
115
|
+
|
|
116
|
+
未完成的一致性实验已作为开发数据迁到 `tasks/code-harness/`:包含三个模式共
|
|
117
|
+
150 个历史 case、行为配置、选定 baseline,以及直接调用本仓库统一 runtime 的
|
|
118
|
+
输入重建、工具 replay、behavior 和 probe runner。重复的原始 JSONL、ignored
|
|
119
|
+
中间报告和旧 runtime 没有复制。`package.json#files` 不包含 `tasks/` 或这些实验
|
|
120
|
+
脚本,因此它们不会进入 npm/SEA 运行包,也不会形成第二套 runtime。
|
|
121
|
+
|
|
122
|
+
只有在两组模式确实需要独立版本、独立依赖或不同发布权限时,才值得增加两个
|
|
123
|
+
很薄的入口包;即便如此,共享核心仍应留在本仓库,而不是复制实现。
|
package/docs/SDK.md
CHANGED
|
@@ -289,6 +289,10 @@ if (
|
|
|
289
289
|
| `start` | Turn 已开始 |
|
|
290
290
|
| `reasoning-start/delta/end` | reasoning 流 |
|
|
291
291
|
| `text-start/delta/end` | 最终文本流 |
|
|
292
|
+
| `model.start` | 模型请求开始,包含 step 与实际 offered tools |
|
|
293
|
+
| `model.retry` | 流式模型请求正在自动重试,包含 attempt 与 error;丢弃本次请求此前的 delta |
|
|
294
|
+
| `model.complete` | 模型请求完成,包含 finish reason 与 usage |
|
|
295
|
+
| `compaction` | 上下文压缩完成;其 usage 只通过此事件上报 |
|
|
292
296
|
| `tool-input-start/delta/available` | 模型正在生成工具调用 |
|
|
293
297
|
| `tool-output-available` | 工具执行结果 |
|
|
294
298
|
| `data-agent-status` | 当前模型或工具阶段 |
|
|
@@ -337,6 +341,16 @@ return [
|
|
|
337
341
|
];
|
|
338
342
|
```
|
|
339
343
|
|
|
344
|
+
如果调用方选择跳过,返回结构化响应。Agent 会收到标准 skipped tool result 并
|
|
345
|
+
继续当前 Turn:
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
return {
|
|
349
|
+
answers: [],
|
|
350
|
+
skipped: true,
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
340
354
|
### UI 手动回答
|
|
341
355
|
|
|
342
356
|
不传 `onInputRequired`,收到事件后渲染自己的 UI:
|
|
@@ -354,6 +368,15 @@ for await (const event of session.stream({
|
|
|
354
368
|
}
|
|
355
369
|
```
|
|
356
370
|
|
|
371
|
+
手动 UI 也可以跳过:
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
await session.respondToInput(request.requestId, {
|
|
375
|
+
answers: [],
|
|
376
|
+
skipped: true,
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
357
380
|
答案格式:
|
|
358
381
|
|
|
359
382
|
```ts
|
|
@@ -545,7 +568,7 @@ session.retry(options?)
|
|
|
545
568
|
session.upload(file)
|
|
546
569
|
session.download(path)
|
|
547
570
|
session.workspaceUrl(path)
|
|
548
|
-
session.respondToInput(requestId,
|
|
571
|
+
session.respondToInput(requestId, answersOrResponse)
|
|
549
572
|
session.cancel()
|
|
550
573
|
session.undo()
|
|
551
574
|
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
You are an expert fullstack developer building web applications with Next.js (App Router) and PostgreSQL via Drizzle ORM. You will use the provided tools to view, create, and edit files in the project.
|
|
2
|
+
For any user prompt, always try to generate a working fullstack web application. Always just update the code instead of asking the user to confirm details.
|
|
3
|
+
|
|
4
|
+
## Critical File Operations
|
|
5
|
+
|
|
6
|
+
All file operations must be done exclusively through the provided tools. After using a tool, provide only a brief summary of what you did - DO NOT output the actual code content in your response text.
|
|
7
|
+
You can use 'list_files', 'grep_files', 'glob_files', and 'bash' to explore the project, search file contents by regex, and discover files by name pattern.
|
|
8
|
+
|
|
9
|
+
## Web Research
|
|
10
|
+
|
|
11
|
+
You have access to 'web_search' and 'web_fetch' tools for researching information on the internet.
|
|
12
|
+
- Use 'web_search' to find documentation, API references, examples, or any facts you need. This is especially useful when the user asks you to integrate a third-party API or library you're not fully familiar with.
|
|
13
|
+
- Use 'web_fetch' to read the content of a specific web page, such as documentation or API reference pages found via search.
|
|
14
|
+
- When the user's request involves a specific API, service, or library, proactively search for its documentation to ensure you use the correct endpoints, parameters, and authentication methods rather than guessing.
|
|
15
|
+
|
|
16
|
+
## Task Planning
|
|
17
|
+
|
|
18
|
+
You have a maximum of 50 sequential tool-calling steps to complete the task. Plan your approach carefully and prioritize the most critical changes first to work within this limit.
|
|
19
|
+
|
|
20
|
+
For each file you create or edit, you must first explain what you are about to do, then call the tool, then confirm the result.
|
|
21
|
+
|
|
22
|
+
Do not ask me for anything. Go with your recommendation.
|
|
23
|
+
|
|
24
|
+
## Database
|
|
25
|
+
|
|
26
|
+
The project connects to a local PostgreSQL instance via Drizzle ORM.
|
|
27
|
+
- The database connection is configured in `src/db/index.ts` and reads `DATABASE_URL` from the `.env` file.
|
|
28
|
+
- Use Drizzle ORM for all database interactions. Import the `db` client from `@/db`.
|
|
29
|
+
- Tailwind CSS is already installed and wired through `src/app/globals.css`, so you can use Tailwind utility classes immediately.
|
|
30
|
+
- When defining new tables, edit `src/db/schema.ts` and use `drizzle-orm/pg-core`.
|
|
31
|
+
- If you need to apply schema changes in a fresh sandbox, call `build_and_start` first so the environment is bootstrapped and dependencies are installed.
|
|
32
|
+
- After `build_and_start` has prepared the environment, you may use the `bash` tool to run `npx drizzle-kit push` to apply schema changes directly without migration files.
|
|
33
|
+
- If you apply schema changes after a previously passing validation run, rerun the full validation sequence and end with `build_and_start` again.
|
|
34
|
+
- You can also run raw SQL via the bash tool: `psql postgresql://postgres:postgres@127.0.0.1:5432/app_db -c "YOUR SQL"`
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
The platform builds and starts the preview after your tool calls complete.
|
|
39
|
+
Do not assume there is a running app server while you edit files.
|
|
40
|
+
Do not leave behind long-lived `next dev` or `next start` processes unless you are debugging a blocker.
|
|
41
|
+
ALWAYS create complete, functional fullstack web applications.
|
|
42
|
+
NEVER edit package.json directly. Use the 'install_npm_packages' tool to install new packages.
|
|
43
|
+
|
|
44
|
+
## Final Validation
|
|
45
|
+
|
|
46
|
+
Before you finish, you MUST use the `bash` tool to run all of these commands from the project root:
|
|
47
|
+
- `bash -lc 'set -o pipefail; npx next typegen 2>&1 | tee /tmp/next-typegen.log'`
|
|
48
|
+
- `bash -lc 'set -o pipefail; npm exec tsc -- --noEmit --pretty false 2>&1 | tee /tmp/tsc.log'`
|
|
49
|
+
- `bash -lc 'set -o pipefail; npm run build 2>&1 | tee /tmp/build.log'`
|
|
50
|
+
|
|
51
|
+
After those commands pass, you MUST call the `build_and_start` tool. This tool bootstraps the database, builds the app, starts the production server, and verifies `/api/health`.
|
|
52
|
+
|
|
53
|
+
Do not run `npm run start` or `next start` directly via `bash` as your final validation step.
|
|
54
|
+
Do not finish until type generation, TypeScript, production build, and `build_and_start` all pass.
|
|
55
|
+
Do not treat `npm run typecheck` as sufficient final validation.
|
|
56
|
+
If any validation command fails, immediately inspect the matching log before fixing the code:
|
|
57
|
+
- `cat /tmp/next-typegen.log`
|
|
58
|
+
- `cat /tmp/tsc.log`
|
|
59
|
+
- `cat /tmp/build.log`
|
|
60
|
+
If `build_and_start` fails, carefully inspect the returned `stage` and `logTail` before fixing the code.
|
|
61
|
+
If any validation step fails, keep fixing the project and do not finish yet.
|
|
62
|
+
If you make any code, package, or schema change after a passing validation run, rerun the full validation sequence before finishing.
|
|
63
|
+
Do not rely on the platform's post-turn preview build as proof the task is done; you must confirm the build yourself during the turn.
|
|
64
|
+
|
|
65
|
+
## Environment Variables
|
|
66
|
+
|
|
67
|
+
The user may have configured environment variable secrets (API keys, tokens, etc.) for this sandbox.
|
|
68
|
+
- Server-side code (API routes, server components, route handlers): access via `process.env.KEY_NAME`
|
|
69
|
+
- Client-side code: only `NEXT_PUBLIC_*` prefixed vars are exposed to the browser bundle
|
|
70
|
+
- For external API calls that require secrets, create an API route under `app/api/` that reads `process.env.KEY_NAME` and proxies the request — this keeps secrets server-side
|
|
71
|
+
- Do NOT hardcode API keys or secrets — always read from `process.env`
|
|
72
|
+
|
|
73
|
+
## Remember
|
|
74
|
+
|
|
75
|
+
Use tools for all file creation and editing. Never output code directly in your response text.
|
|
76
|
+
Feel free to use multiple files in your implementation.
|
|
77
|
+
The preview is rebuilt and restarted after you finish your edits for the turn.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5432/app_db
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
2
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
3
|
+
import nextTs from "eslint-config-next/typescript";
|
|
4
|
+
|
|
5
|
+
export default defineConfig([
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts"]),
|
|
9
|
+
]);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nextjs-postgresql-template",
|
|
3
|
+
"private": true,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev": "next dev",
|
|
6
|
+
"build": "next build",
|
|
7
|
+
"start": "next start",
|
|
8
|
+
"lint": "eslint .",
|
|
9
|
+
"typecheck": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"dotenv": "17.3.1",
|
|
13
|
+
"drizzle-orm": "0.45.2",
|
|
14
|
+
"next": "16.2.6",
|
|
15
|
+
"pg": "8.20.0",
|
|
16
|
+
"react": "19.2.6",
|
|
17
|
+
"react-dom": "19.2.6"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@tailwindcss/postcss": "4.1.17",
|
|
21
|
+
"@types/node": "22.19.15",
|
|
22
|
+
"@types/pg": "8.18.0",
|
|
23
|
+
"@types/react": "19.2.14",
|
|
24
|
+
"@types/react-dom": "19.2.3",
|
|
25
|
+
"drizzle-kit": "0.31.10",
|
|
26
|
+
"eslint": "9.39.4",
|
|
27
|
+
"eslint-config-next": "16.2.6",
|
|
28
|
+
"postcss": "8.5.8",
|
|
29
|
+
"tailwindcss": "4.1.17",
|
|
30
|
+
"typescript": "5.9.3"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { db } from "@/db";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
|
|
6
|
+
export async function GET() {
|
|
7
|
+
try {
|
|
8
|
+
await db.execute(sql`select 1`);
|
|
9
|
+
return Response.json({ ok: true });
|
|
10
|
+
} catch {
|
|
11
|
+
return Response.json({ ok: false }, { status: 500 });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
export const metadata: Metadata = {
|
|
6
|
+
title: "Arena Next.js PostgreSQL Starter",
|
|
7
|
+
description: "Starter template with Next.js, Drizzle, and PostgreSQL.",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
11
|
+
return (
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<body className="bg-slate-100 text-slate-900 antialiased">{children}</body>
|
|
14
|
+
</html>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { db } from "@/db";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
|
|
6
|
+
export default async function HomePage() {
|
|
7
|
+
await db.execute(sql`select 1`);
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<main className="grid min-h-screen place-items-center px-6 py-12">
|
|
11
|
+
<section className="w-full max-w-2xl rounded-3xl bg-white p-10 shadow-[0_24px_60px_rgba(16,24,40,0.12)]">
|
|
12
|
+
<p className="m-0 text-sm uppercase tracking-[0.08em] text-slate-600">Starter template</p>
|
|
13
|
+
<h1 className="mt-4 text-[clamp(2rem,5vw,3.25rem)] font-semibold leading-[1.05] text-slate-950">
|
|
14
|
+
Arena Next.js PostgreSQL Starter
|
|
15
|
+
</h1>
|
|
16
|
+
<p className="mt-4 text-base text-slate-700">
|
|
17
|
+
Server-rendered with Next.js after a successful PostgreSQL query through Drizzle.
|
|
18
|
+
</p>
|
|
19
|
+
</section>
|
|
20
|
+
</main>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
2
|
+
import { Pool } from "pg";
|
|
3
|
+
|
|
4
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
5
|
+
|
|
6
|
+
if (!databaseUrl) {
|
|
7
|
+
throw new Error("DATABASE_URL is required");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const globalForDb = globalThis as typeof globalThis & {
|
|
11
|
+
__arenaNextJsPostgresqlPool?: Pool;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const pool =
|
|
15
|
+
globalForDb.__arenaNextJsPostgresqlPool ??
|
|
16
|
+
new Pool({
|
|
17
|
+
connectionString: databaseUrl,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (process.env.NODE_ENV !== "production") {
|
|
21
|
+
globalForDb.__arenaNextJsPostgresqlPool = pool;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const db = drizzle(pool);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": false,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"baseUrl": ".",
|
|
17
|
+
"paths": {
|
|
18
|
+
"@/*": ["./src/*"]
|
|
19
|
+
},
|
|
20
|
+
"plugins": [{ "name": "next" }]
|
|
21
|
+
},
|
|
22
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
23
|
+
"exclude": ["node_modules"]
|
|
24
|
+
}
|