@qwen-code/arena-agent 0.0.9-dev.8 → 0.0.10-dev.0
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 +54 -19
- package/README.md +218 -45
- package/dist/agent.d.ts +4 -2
- package/dist/agent.js +167 -21
- package/dist/agent.js.map +1 -1
- package/dist/anthropic.d.ts +1 -0
- package/dist/anthropic.js +90 -23
- package/dist/anthropic.js.map +1 -1
- 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 +10 -0
- package/dist/brave-search.js +238 -0
- package/dist/brave-search.js.map +1 -0
- package/dist/canonical-data.js +2 -2
- package/dist/canonical-data.js.map +1 -1
- package/dist/cli.js +64 -18
- package/dist/cli.js.map +1 -1
- package/dist/code-tools.d.ts +0 -5
- package/dist/code-tools.js +29 -353
- package/dist/code-tools.js.map +1 -1
- package/dist/compaction.js +8 -2
- package/dist/compaction.js.map +1 -1
- package/dist/config.d.ts +30 -0
- package/dist/config.js +57 -3
- package/dist/config.js.map +1 -1
- package/dist/fetch-page.d.ts +1 -0
- package/dist/fetch-page.js +1 -1
- package/dist/fetch-page.js.map +1 -1
- package/dist/history.d.ts +3 -2
- package/dist/history.js +7 -2
- package/dist/history.js.map +1 -1
- package/dist/image-input-fallback.d.ts +9 -0
- package/dist/image-input-fallback.js +47 -0
- package/dist/image-input-fallback.js.map +1 -0
- package/dist/image.d.ts +16 -0
- package/dist/image.js +380 -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/model-capabilities.js +12 -2
- package/dist/model-capabilities.js.map +1 -1
- package/dist/model-diagnostics.js +16 -5
- package/dist/model-diagnostics.js.map +1 -1
- package/dist/model-router-media.d.ts +26 -0
- package/dist/model-router-media.js +274 -0
- package/dist/model-router-media.js.map +1 -0
- package/dist/openai-responses.d.ts +28 -0
- package/dist/openai-responses.js +473 -0
- package/dist/openai-responses.js.map +1 -0
- package/dist/process-manager.d.ts +38 -0
- package/dist/process-manager.js +486 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/prompts.js +3 -1
- package/dist/prompts.js.map +1 -1
- package/dist/provider.d.ts +7 -0
- package/dist/provider.js +291 -27
- 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 +9 -2
- package/dist/sdk.js +5 -2
- package/dist/sdk.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.js +112 -21
- package/dist/server.js.map +1 -1
- package/dist/spec.js +15 -1
- package/dist/spec.js.map +1 -1
- package/dist/tools.d.ts +2 -1
- package/dist/tools.js +250 -340
- package/dist/tools.js.map +1 -1
- package/dist/tui.d.ts +3 -0
- package/dist/tui.js +18 -11
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +17 -6
- package/dist/voice-registry.d.ts +30 -0
- package/dist/voice-registry.js +82 -0
- package/dist/voice-registry.js.map +1 -0
- package/dist/web/app.js +67 -6
- package/dist/web/app.js.map +1 -1
- package/docs/BINARY_DISTRIBUTION.md +25 -18
- package/docs/MODES_AND_RELEASES.md +8 -4
- package/docs/SDK.md +28 -4
- package/package.json +21 -3
- package/web/styles.css +28 -7
package/.env.example
CHANGED
|
@@ -7,6 +7,14 @@ OPENAI_MODEL=openai/qwen-latest-series-invite-beta-v92
|
|
|
7
7
|
OPENAI_BASE_URL=
|
|
8
8
|
OPENAI_API_KEY=
|
|
9
9
|
|
|
10
|
+
# Auto mode uses Responses for GPT model names and Chat Completions otherwise.
|
|
11
|
+
# Native Responses preserves opaque OpenAI reasoning across tool steps and
|
|
12
|
+
# separate CLI turns by replaying encrypted output items with store=false.
|
|
13
|
+
# Set chat to force Chat Completions.
|
|
14
|
+
# ARENA_OPENAI_API=auto
|
|
15
|
+
# ARENA_OPENAI_API=responses
|
|
16
|
+
# ARENA_OPENAI_API=chat
|
|
17
|
+
|
|
10
18
|
# Unified runtime mode. Canonical values are shown; full_stack/fullstack and
|
|
11
19
|
# single_html/single-html remain accepted compatibility aliases.
|
|
12
20
|
ARENA_HARNESS_MODE=arena
|
|
@@ -50,6 +58,10 @@ ARENA_HARNESS_MODE=arena
|
|
|
50
58
|
# ARENA_THINKING_BUDGET=81920
|
|
51
59
|
# ARENA_ENABLE_THINKING=true
|
|
52
60
|
# ARENA_PRESERVE_THINKING=true
|
|
61
|
+
# Remove Qwen from the identity-model list in Arena system prompts. Canonical
|
|
62
|
+
# prompt fixtures and Code Arena prompts are unchanged.
|
|
63
|
+
# ARENA_EXCLUDE_QWEN_FROM_SYSTEM_PROMPT=false
|
|
64
|
+
# CLI equivalent: --exclude-qwen-from-system-prompt
|
|
53
65
|
# Context is summarized before a model call when the estimated input reaches
|
|
54
66
|
# this fraction of the configured model context window.
|
|
55
67
|
# ARENA_CONTEXT_WINDOW=1000000
|
|
@@ -58,12 +70,23 @@ ARENA_HARNESS_MODE=arena
|
|
|
58
70
|
# ARENA_EXTRA_BODY={"enable_thinking":true}
|
|
59
71
|
# Transient model failures use full-jitter exponential backoff. The retry delay
|
|
60
72
|
# is capped by ARENA_MODEL_RETRY_MAX_MS and honors Retry-After when present.
|
|
61
|
-
# ARENA_MODEL_MAX_RETRIES=
|
|
73
|
+
# ARENA_MODEL_MAX_RETRIES=10
|
|
62
74
|
# ARENA_MODEL_RETRY_BASE_MS=1000
|
|
63
|
-
# ARENA_MODEL_RETRY_MAX_MS=
|
|
75
|
+
# ARENA_MODEL_RETRY_MAX_MS=120000
|
|
64
76
|
# A stream that stays open but delivers no bytes for this long is aborted and
|
|
65
77
|
# retried like a network fault (0 disables). Some gateways stall silently.
|
|
66
78
|
# ARENA_MODEL_STREAM_IDLE_TIMEOUT_MS=300000
|
|
79
|
+
# Explicit main-model media capability overrides. When image support resolves to
|
|
80
|
+
# false, the optional fallback model converts Arena read_file images to text.
|
|
81
|
+
# ARENA_MODEL_SUPPORTS_IMAGE_INPUT=false
|
|
82
|
+
# ARENA_IMAGE_INPUT_FALLBACK_MODEL=qwen3.7-plus
|
|
83
|
+
# Inline image budget before downscaling: max pixels per edge and max 28x28
|
|
84
|
+
# patches. Images within both limits are sent unchanged; larger ones are
|
|
85
|
+
# downscaled to fit and re-encoded as JPEG. Defaults match the captured
|
|
86
|
+
# baseline; raise both for long screenshots (a 1920x5344 full-page capture
|
|
87
|
+
# needs about 8192 edge and 13179 patches to pass through unchanged).
|
|
88
|
+
# ARENA_IMAGE_MAX_EDGE=1568
|
|
89
|
+
# ARENA_IMAGE_MAX_PATCHES=1568
|
|
67
90
|
|
|
68
91
|
# Optional headless ask_user delegation. When enabled, `arena -p` sends the
|
|
69
92
|
# current questions plus a serialized ATIF trajectory to this JSON endpoint.
|
|
@@ -72,10 +95,13 @@ ARENA_HARNESS_MODE=arena
|
|
|
72
95
|
# ARENA_ASK_USER_HANDLER_URL=http://127.0.0.1:8080/v1/ask-user
|
|
73
96
|
# ARENA_ASK_USER_TIMEOUT_MS=60000
|
|
74
97
|
|
|
75
|
-
# Dynamic session metrics.
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
98
|
+
# Dynamic session metrics. Disabled by default: with the switch off the daemon
|
|
99
|
+
# performs no metric analysis, persists no metrics, and emits no
|
|
100
|
+
# data-session-metrics events. Enable it to compute a snapshot after every
|
|
101
|
+
# user-facing turn; high-confidence Bash cases use deterministic rules, while
|
|
102
|
+
# ambiguous Bash attribution/termination plus user praise, complaint,
|
|
103
|
+
# correction, repair-attempt, and repair-verdict classification use this
|
|
104
|
+
# tool-free structured side query.
|
|
79
105
|
# ARENA_METRICS_SIDE_QUERY_ENABLED=true
|
|
80
106
|
# ARENA_METRICS_SIDE_QUERY_MODEL=openai/qwen-latest-series-invite-beta-v92
|
|
81
107
|
# ARENA_METRICS_SIDE_QUERY_MAX_TOKENS=800
|
|
@@ -93,29 +119,38 @@ ARENA_HARNESS_MODE=arena
|
|
|
93
119
|
# defaults to ~/.arena so runs never write into the task workspace.
|
|
94
120
|
# ARENA_HOME=~/.arena
|
|
95
121
|
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
122
|
+
# Search, page reading, image generation, and speech through ModelRouter/Routify.
|
|
123
|
+
ROUTIFY_API_KEY=
|
|
124
|
+
# ROUTIFY_WEB_SEARCH_URL=https://routify-pub.alibaba-inc.com/protocol/compatible-mode/res/v1/llm/context
|
|
125
|
+
# ROUTIFY_IMAGE_SEARCH_URL=https://routify-pub.alibaba-inc.com/protocol/brave/res/v1/images/search
|
|
126
|
+
# ROUTIFY_VERTEX_BASE_URL=https://routify-pub.alibaba-inc.com/protocol/vertex/v1beta
|
|
127
|
+
# ARENA_WEB_SEARCH_MODEL=brave.llm-context
|
|
128
|
+
# CODE_HARNESS_WEB_SEARCH_MODEL=brave.llm-context
|
|
129
|
+
# Optional fetch_page/web_fetch path: Firecrawl first, then Jina Reader.
|
|
130
|
+
# CODE_HARNESS_ROUTIFY_WEB_FETCH_ENABLED=false
|
|
131
|
+
# ARENA_IMAGE_MODEL=gemini-2.5-flash-image
|
|
132
|
+
# ARENA_IMAGE_SIZE=1024*1024
|
|
133
|
+
# CODE_HARNESS_IMAGE_MODEL=gemini-2.5-flash-image
|
|
134
|
+
# CODE_HARNESS_IMAGE_SIZE=1024*1024
|
|
135
|
+
# ARENA_SPEECH_MODEL=doubao-tts
|
|
136
|
+
# ARENA_SPEECH_VOICE=zh_female_vv_uranus_bigtts
|
|
137
|
+
|
|
138
|
+
# start_process automatically checks E2B preview hosts when E2B_SANDBOX_ID is
|
|
139
|
+
# present. For another preview proxy, use {port} and optionally {sandboxId}:
|
|
140
|
+
# ARENA_PREVIEW_HOST_TEMPLATE={port}-{sandboxId}.e2b.app
|
|
141
|
+
# ROUTIFY_MEDIA_MAX_RETRIES=5
|
|
106
142
|
|
|
107
143
|
# Code Arena stock photo/video search used by fetch_media.
|
|
108
144
|
# PEXELS_API_KEY=
|
|
109
145
|
# CODE_HARNESS_MEDIA_CACHE_DIR=/tmp/code-harness-media-cache
|
|
110
146
|
# CODE_HARNESS_MEDIA_CACHE_TTL_MS=86400000
|
|
111
147
|
|
|
112
|
-
# Full Stack build_and_start runtime.
|
|
113
|
-
#
|
|
148
|
+
# Full Stack build_and_start runtime. PostgreSQL and psql are environment
|
|
149
|
+
# prerequisites, matching the captured sandbox baseline.
|
|
114
150
|
# CODE_HARNESS_PREVIEW_PORT=3000
|
|
115
151
|
# CODE_HARNESS_PREVIEW_URL=http://127.0.0.1:3000
|
|
116
152
|
# CODE_HARNESS_FULLSTACK_BUILD_TIMEOUT_MS=300000
|
|
117
153
|
# CODE_HARNESS_BASH_TIMEOUT_SECONDS=300
|
|
118
|
-
# CODE_HARNESS_POSTGRES_IMAGE=postgres:16-alpine
|
|
119
154
|
|
|
120
155
|
# Optional LibreOffice executable for read_file support of legacy .doc/.ppt/.xls.
|
|
121
156
|
# ARENA_SOFFICE_PATH=/usr/local/bin/soffice
|
package/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# Arena CodeAgent Harness
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
harness。运行时只依赖 Node.js,不再依赖 Python:
|
|
3
|
+
这是一个基于 `message.json` 与 `tools.json` 所定义消息和工具契约的 TypeScript
|
|
4
|
+
CodeAgent harness。运行时只依赖 Node.js,不再依赖 Python:
|
|
5
5
|
|
|
6
6
|
- `arena -p ...`:headless 单轮入口,支持文本、完整 JSON 和 NDJSON 流。
|
|
7
7
|
- `arena tui`:终端多轮对话,实时输出并自动保存、恢复历史。
|
|
8
8
|
- `arena serve`:HTTP daemon、Web UI 与双通道 SSE 实时接口。
|
|
9
9
|
- Agent loop:流式 assistant → tool call → tool result → assistant。
|
|
10
|
-
-
|
|
10
|
+
- 15 个工具按照 `tools.json` 中的 Draft-07 schema 提供参数校验。
|
|
11
|
+
|
|
12
|
+
本文提及的第三方产品、模型与服务名称仅用于说明兼容性和配置方式,不表示相关
|
|
13
|
+
权利人对本项目的认可或背书;相关商标归各自权利人所有。使用者应自行确认并遵守
|
|
14
|
+
所接入模型、数据源和在线服务的许可、服务条款及适用法律。
|
|
11
15
|
|
|
12
16
|
## 源码与 SDK 安装
|
|
13
17
|
|
|
@@ -49,6 +53,9 @@ npm ci
|
|
|
49
53
|
npm run package:binary
|
|
50
54
|
```
|
|
51
55
|
|
|
56
|
+
其中 `linux-x64` 产物使用 glibc 2.17 兼容的内嵌 Node.js Runtime,目标机器无需
|
|
57
|
+
安装 Node.js;Alpine/musl 系统请使用独立的 `linux-x64-musl` 产物。
|
|
58
|
+
|
|
52
59
|
命令会生成 `build/sea/arena`(Windows 为 `arena.exe`),并打出当前平台包和
|
|
53
60
|
`@qwen-code/arena-cli` 的 npm tarball。二进制必须针对目标操作系统、CPU 架构和
|
|
54
61
|
Linux libc 分别构建;不能把 macOS 上生成的文件直接用于 Linux。
|
|
@@ -83,11 +90,61 @@ code-harness -p '做一个单文件网页' --mode html
|
|
|
83
90
|
`CODE_HARNESS_MODE`、`ARENA_MODE` 及旧模式别名。详细目录和发包决策见
|
|
84
91
|
[`docs/MODES_AND_RELEASES.md`](docs/MODES_AND_RELEASES.md)。
|
|
85
92
|
|
|
93
|
+
如需完全替换模型收到的 system prompt,可在任一运行入口传入
|
|
94
|
+
`--system-prompt <text>`:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
arena -p '分析这个目录' --system-prompt '你是一名精简的代码审查助手。'
|
|
98
|
+
arena tui --system-prompt '始终先给结论,再解释原因。'
|
|
99
|
+
arena serve --system-prompt '只使用中文回复。'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
该参数只在运行时覆盖第一条 system message,不会修改 canonical prompt fixture;
|
|
103
|
+
续跑已有 session 时,当前传入的值会替换历史中的 system message。未传参数时,
|
|
104
|
+
日期、workspace 和 mode 对应的现有 prompt 生成逻辑保持不变。
|
|
105
|
+
|
|
106
|
+
如需保留当前 mode 生成的 system prompt,只在末尾追加任务或部署指令,可传入
|
|
107
|
+
`--append-system-prompt <text>`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
arena -p '分析这个目录' --append-system-prompt '回答保持精简。'
|
|
111
|
+
arena tui --append-system-prompt '始终先给结论,再解释原因。'
|
|
112
|
+
arena serve --append-system-prompt '只使用中文回复。'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
追加内容会作为独立段落放在运行时 system message 末尾,因此原有日期、workspace、
|
|
116
|
+
工具和 mode 指令保持不变,也不会修改 canonical prompt fixture。同一会话内只会追加
|
|
117
|
+
一次,不会随 turn 重复累积。使用 headless CLI 续跑 session 时,需要再次传入相同的
|
|
118
|
+
追加参数。`--system-prompt` 与 `--append-system-prompt` 可以同时使用,此时先完整
|
|
119
|
+
替换,再追加指定文本。
|
|
120
|
+
|
|
121
|
+
`arena serve` 是一个例外:未显式传入 `--system-prompt` 时,它会保留现有系统
|
|
122
|
+
提示词中的日期、workspace、工具和 mode 指令,但默认将身份声明设为 `Qwen`。
|
|
123
|
+
显式传入 `--system-prompt` 时仍会完整替换系统提示词;仅传
|
|
124
|
+
`--append-system-prompt` 时,则先应用该 Qwen 身份变换,再追加文本。
|
|
125
|
+
|
|
126
|
+
Arena 模式下,如需从 system prompt 的身份模型列表中移除 `Qwen`,可增加
|
|
127
|
+
`--exclude-qwen-from-system-prompt`,或设置
|
|
128
|
+
`ARENA_EXCLUDE_QWEN_FROM_SYSTEM_PROMPT=true`。CLI 开关优先于环境变量:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
arena -p '分析这个目录' --exclude-qwen-from-system-prompt
|
|
132
|
+
arena tui --exclude-qwen-from-system-prompt
|
|
133
|
+
arena serve --exclude-qwen-from-system-prompt
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
三个 Code Arena 模式的兼容性测试集、工具回归测试和模型行为评估入口见
|
|
137
|
+
[`tasks/code-harness/README.md`](tasks/code-harness/README.md);这些开发数据不会
|
|
138
|
+
进入 npm 或 SEA 发布包。
|
|
139
|
+
|
|
86
140
|
## 模型
|
|
87
141
|
|
|
88
|
-
TypeScript
|
|
89
|
-
|
|
90
|
-
OpenAI
|
|
142
|
+
TypeScript 运行时根据模型前缀与名称选择协议:`anthropic/` 使用原生
|
|
143
|
+
Messages,`gemini/` 使用 Google 的 OpenAI-compatible 接口;`openai/` 或
|
|
144
|
+
无前缀模型使用 OpenAI 传输,其中模型名包含 `gpt`(大小写不敏感)时默认
|
|
145
|
+
使用 Responses,其余使用 Chat Completions。无前缀且名称包含 `claude` 时
|
|
146
|
+
使用 Anthropic Messages。显式 provider 前缀与 `ARENA_OPENAI_API` 始终优先。
|
|
147
|
+
LiteLLM 官方提供 Python SDK 或独立 Proxy,因此
|
|
91
148
|
纯 TypeScript 版本使用
|
|
92
149
|
[LiteLLM Proxy](https://docs.litellm.ai/) 作为多 provider 网关:
|
|
93
150
|
|
|
@@ -123,10 +180,19 @@ export OPENAI_API_KEY=...
|
|
|
123
180
|
```
|
|
124
181
|
|
|
125
182
|
`OPENAI_BASE_URL` / `OPENAI_API_KEY` 是统一的模型连接入口,变量名不决定
|
|
126
|
-
wire protocol。`OPENAI_MODEL=anthropic/...`
|
|
127
|
-
Anthropic Messages payload 并使用 `x-api-key
|
|
128
|
-
`<base>/chat/completions`
|
|
129
|
-
|
|
183
|
+
wire protocol。`OPENAI_MODEL=anthropic/...` 会向 `<base>/messages` 发送
|
|
184
|
+
Anthropic Messages payload 并使用 `x-api-key`;OpenAI 路由根据上述规则向
|
|
185
|
+
`<base>/chat/completions` 或 `<base>/responses` 发送 Bearer 请求。Responses
|
|
186
|
+
路径固定使用 `store=false`,不会发送 `previous_response_id` 或 conversation。
|
|
187
|
+
每次响应完成时,Harness 会把 `reasoning`、`function_call` 和 assistant message
|
|
188
|
+
等原生 output items 原样保存在 assistant 历史中;其中 reasoning 的
|
|
189
|
+
`encrypted_content` 是 OpenAI 返回的不可读加密载荷。后续工具 step 和跨 CLI
|
|
190
|
+
回合会把这些 output items 连同 function output 一起完整回放到下一次 `input`,
|
|
191
|
+
从而在不依赖 provider 端存储的情况下保留隐藏 reasoning。请求显式包含
|
|
192
|
+
`reasoning.encrypted_content`;GPT-5.6 还会使用 `reasoning.context=all_turns`。
|
|
193
|
+
设置 `ARENA_OPENAI_API=chat` 或 `responses` 可覆盖 GPT 的自动选择。
|
|
194
|
+
该开关不作用于 LiteLLM、Gemini 或 Anthropic 路由。如未设置统一入口,
|
|
195
|
+
Anthropic 可回退到 `ANTHROPIC_BASE_URL` /
|
|
130
196
|
`ANTHROPIC_API_KEY`。
|
|
131
197
|
|
|
132
198
|
Anthropic 直连默认只用 `x-api-key` 鉴权(同时携带 Authorization 会让部分
|
|
@@ -143,11 +209,11 @@ Anthropic 直连在原生协议上完整支持 thinking。旧版 Claude 和非 C
|
|
|
143
209
|
budget。Anthropic 要求启用 thinking 时不调整 temperature,此时不发送该
|
|
144
210
|
参数。带签名的 thinking/redacted_thinking block 会原样保存在对应 assistant
|
|
145
211
|
消息的 `reasoning_details` 字段——
|
|
146
|
-
Anthropic 要求 tool-use 续跑时回传签名 thinking block
|
|
212
|
+
Anthropic 要求 tool-use 续跑时回传签名 thinking block,恢复历史上下文时会按
|
|
147
213
|
原顺序还原;无签名的 thinking block(部分网关返回 `signature: ""`)
|
|
148
|
-
|
|
214
|
+
不会再次发送,因为协议不需要它们,而且某些网关收到会挂起。
|
|
149
215
|
`reasoning_content` 仍是纯文本推理,历史契约不变。向
|
|
150
|
-
OpenAI-compatible
|
|
216
|
+
OpenAI-compatible 服务发送同一份历史时,`reasoning_details` 与 `usage`
|
|
151
217
|
一样在 wire 边界剥离。usage 会映射为 OpenAI 风格字段(`prompt_tokens`
|
|
152
218
|
含 cache 创建/读取部分),同时保留 `input_tokens`、
|
|
153
219
|
`cache_read_input_tokens` 等原生字段。`OPENAI_BASE_URL` 对 anthropic
|
|
@@ -174,8 +240,9 @@ ARENA_COMPACTION_SUMMARY_MAX_TOKENS=8192
|
|
|
174
240
|
```
|
|
175
241
|
|
|
176
242
|
可选的 `ARENA_REASONING_EFFORT` 支持 `low`、`medium`、`high`、`xhigh`
|
|
177
|
-
和 `max` 五档;
|
|
178
|
-
Anthropic Messages 请求映射为
|
|
243
|
+
和 `max` 五档;Chat Completions 请求使用 `reasoning_effort`,Responses
|
|
244
|
+
请求使用 `reasoning.effort`,原生 Anthropic Messages 请求映射为
|
|
245
|
+
`output_config.effort`。不会按模型静默
|
|
179
246
|
降档;目标模型或兼容网关不支持所选档位时,由服务端返回明确错误。
|
|
180
247
|
`ARENA_DISALLOWED_TOOLS` 是 JSON 字符串数组,工具名精确匹配:
|
|
181
248
|
|
|
@@ -190,13 +257,17 @@ ARENA_DISALLOWED_TOOLS=["bash","write_file"]
|
|
|
190
257
|
参数覆盖,也会原样写入 `history.json` 的
|
|
191
258
|
`metadata.parameters.extra_body`。
|
|
192
259
|
|
|
193
|
-
`
|
|
194
|
-
|
|
260
|
+
`ROUTIFY_API_KEY` 供 `web_search`、`image_search`、`generate_image` 和
|
|
261
|
+
`generate_speech` 使用;开启
|
|
262
|
+
`CODE_HARNESS_ROUTIFY_WEB_FETCH_ENABLED` 后,Arena 的 `fetch_page` 和 Code Arena 的
|
|
263
|
+
`web_fetch` 也复用该密钥,通过 Routify 先调用 Firecrawl,失败时回退到
|
|
264
|
+
Jina Reader。
|
|
265
|
+
该密钥不会作为主模型连接的密钥。
|
|
195
266
|
|
|
196
267
|
Harness 会在每次模型调用前估算消息、reasoning、工具 schema 和图片占用;达到
|
|
197
268
|
`ARENA_CONTEXT_WINDOW × ARENA_CONTEXT_COMPACTION_RATIO`(默认 80%)时,调用
|
|
198
269
|
当前模型把已完成的旧回合生成结构化续作摘要。只有发给模型的内存上下文会把
|
|
199
|
-
|
|
270
|
+
旧前缀替换为符合既有会话格式的 leading `<arena-system-message>`;持久化的
|
|
200
271
|
`history.json.messages` 保留原始消息,不会因压缩删除或替换前缀。当前用户回合及
|
|
201
272
|
其后的 tool-call / result 链在模型上下文中保持原样。摘要重点保留目标、硬约束、
|
|
202
273
|
发现、已完成/未完成事项、下一步和相关文件路径;摘要调用默认关闭 thinking,
|
|
@@ -204,20 +275,27 @@ Harness 会在每次模型调用前估算消息、reasoning、工具 schema 和
|
|
|
204
275
|
`ARENA_COMPACTION_SUMMARY_MAX_TOKENS` 控制(默认 8192)。
|
|
205
276
|
|
|
206
277
|
`ARENA_CONTEXT_WINDOW` 应设置为所用模型的真实上下文窗口;默认 `1000000` 是
|
|
207
|
-
|
|
278
|
+
当前默认模型的暂定值。token 数目前是本地保守估算,并非 provider tokenizer
|
|
208
279
|
的精确计数。如果摘要请求失败,Harness 会保留原历史并继续正常模型请求,避免
|
|
209
280
|
摘要服务的瞬时故障直接中断任务。
|
|
210
281
|
|
|
282
|
+
Responses 与其他协议一样,会在每个工具 step 前检查是否需要压缩。由于所有
|
|
283
|
+
reasoning/function-call 状态都由本地 history 携带,压缩不再需要切断或重建 provider
|
|
284
|
+
端 response 链。压缩会把已完成的旧回合替换成续作摘要,同时保留当前 user turn 里的
|
|
285
|
+
加密 reasoning、function call 和 function output;下一次 Responses 请求直接回放这份
|
|
286
|
+
压缩后的本地上下文。持久化的原始 `history.json` 仍保持 append-only。
|
|
287
|
+
|
|
211
288
|
每次模型请求都会通过 OpenAI-compatible 的 `stream_options.include_usage`
|
|
212
289
|
请求 token 用量,并把服务端在最终 chunk 上报的 `usage` 对象原样记录到该轮
|
|
213
290
|
assistant 消息的 `usage` 字段(`history.json` 与事件流中均可见),供训练
|
|
214
|
-
|
|
291
|
+
和成本统计使用。再次发送历史上下文时,`usage` 会在 wire 边界剥离,不会发回
|
|
215
292
|
服务端。`model.complete` 事件同样携带该轮 `usage`;上下文压缩的摘要调用
|
|
216
293
|
不会在历史中留下消息,其用量通过 `compaction` 事件上报,只在事件流中可
|
|
217
294
|
见。不支持 `stream_options` 的服务可通过 `ARENA_EXTRA_BODY` 覆盖该参数。
|
|
218
295
|
|
|
219
296
|
模型请求遇到网络错误、HTTP 408/409/429 或 5xx 时会自动重试,默认最多重试
|
|
220
|
-
|
|
297
|
+
10 次。没有 `Retry-After` 时使用带随机抖动的指数退避,单次等待默认最多
|
|
298
|
+
2 分钟;可通过
|
|
221
299
|
`ARENA_MODEL_MAX_RETRIES`、`ARENA_MODEL_RETRY_BASE_MS` 和
|
|
222
300
|
`ARENA_MODEL_RETRY_MAX_MS` 调整。设 `ARENA_MODEL_MAX_RETRIES=0` 可关闭。
|
|
223
301
|
|
|
@@ -228,6 +306,14 @@ assistant 消息的 `usage` 字段(`history.json` 与事件流中均可见)
|
|
|
228
306
|
`model.retry` 事件(TUI 会显示「reconnecting after a network error」提示)。
|
|
229
307
|
用户主动取消(abort)不会被当作可重试的网络故障。
|
|
230
308
|
|
|
309
|
+
OpenAI Responses 还会检查 HTTP 200 SSE 中的 `error` / `response.failed`
|
|
310
|
+
事件。带 408/409/429/5xx 或明确瞬时错误类型的事件会整轮重试;上游只给文本时,
|
|
311
|
+
仅明确的 `experiencing high demand`、`maximum usage size allowed during peak
|
|
312
|
+
load`、`Provisioned Throughput` 容量错误会重试。容量错误最多重试 5 次
|
|
313
|
+
(`ARENA_MODEL_MAX_RETRIES` 可进一步降低或关闭),每次均重新发送完全相同的
|
|
314
|
+
模型输入,并沿用 full-jitter 指数退避。上下文超限、参数、鉴权、媒体和安全错误
|
|
315
|
+
等永久错误不会因正文中出现 `error` 一词而重试。
|
|
316
|
+
|
|
231
317
|
Agent turn 默认没有模型 step 数上限;设置 `ARENA_MAX_TURNS` 后,达到指定上限
|
|
232
318
|
会返回 error,已经完成的 assistant/tool step 仍会保留。整轮没有内建墙钟时长
|
|
233
319
|
上限,会持续到模型正常结束、请求用户输入、发生不可恢复错误、达到显式配置的
|
|
@@ -292,12 +378,22 @@ Arena 还维护一份有顺序的模型输入模态表,在第一次 HTTP 调
|
|
|
292
378
|
未知模型默认尝试发送,具体路由能力仍以端点返回为准。可以分别用
|
|
293
379
|
`ARENA_MODEL_SUPPORTS_IMAGE_INPUT`、`ARENA_MODEL_SUPPORTS_VIDEO_INPUT`、
|
|
294
380
|
`ARENA_MODEL_SUPPORTS_AUDIO_INPUT` 显式覆盖;覆盖值优先于内置表。
|
|
381
|
+
当主模型被明确判定为不支持图片时,可设置
|
|
382
|
+
`ARENA_IMAGE_INPUT_FALLBACK_MODEL`,让普通 Arena 的图片 `read_file` 先由该模型
|
|
383
|
+
转换为文字;主模型支持图片、模型未知或 Code Arena 模式均不触发此 fallback。
|
|
384
|
+
fallback 不继承 `ARENA_EXTRA_BODY` 或主模型生成参数;原生 Anthropic Messages
|
|
385
|
+
因协议要求会单独使用 `max_tokens: 16384`。
|
|
386
|
+
同一条件下,用户直接附加的图片不会发送给主模型;已有附件文件列表会保留,并提示
|
|
387
|
+
模型调用 `read_file` 获取 fallback 生成的文字版本。
|
|
295
388
|
|
|
296
389
|
输出事件及 JSON 结果中的 `session_id` 就是路径里的 `<sessionId>`。
|
|
297
390
|
`history.json` 的 `messages` 是只追加的原始轨迹;上下文压缩只影响发送给模型的
|
|
298
391
|
临时副本。`metadata` 记录 session、模型以及本次实际生效的 `max_turns`、
|
|
299
|
-
`context_window
|
|
300
|
-
|
|
392
|
+
`context_window`、生成和压缩参数。`tools` 记录最近一次保存时实际提供给模型的
|
|
393
|
+
完整工具定义,包括针对 workspace 的描述改写和不可用工具(未接 `ask_user`
|
|
394
|
+
handler、`ARENA_DISALLOWED_TOOLS`)的过滤结果。daemon 完成一次 turn 后还会写入
|
|
395
|
+
`version: 4`;开启动态指标统计(`ARENA_METRICS_SIDE_QUERY_ENABLED`,默认关闭)
|
|
396
|
+
时还会写入 `metrics`,后者是截至该 turn 的 praise vs. complaint、
|
|
301
397
|
steerability、Bash recovery 与 tool hallucination 增量快照。即使结果为
|
|
302
398
|
`needs_input` 或 `error` 也会保存;旧的 `{"messages":[...]}` 历史仍可直接加载。
|
|
303
399
|
需要跨命令续写同一份显式历史时,可另外传入
|
|
@@ -331,17 +427,17 @@ arena -p 'redraw this photo with the reference face' \
|
|
|
331
427
|
每个附件会被保存到工作区 `uploads/`(模型内可通过
|
|
332
428
|
`/home/user/uploads/<name>` 访问;重名自动加 `-2`、`-3` 后缀,URL 无扩展名
|
|
333
429
|
时按图片字节特征补全扩展名)。本轮 user message 与 daemon 附件上传共用同
|
|
334
|
-
|
|
430
|
+
一构造逻辑,并使用统一的会话部件格式:图片部件
|
|
335
431
|
`{"image": ...}` 在前,随后是 prompt 文本 `{"text": ...}`,最后追加一条
|
|
336
432
|
`<arena-system-message>`,列出保存到 `/home/user/uploads/` 的文件名。单条
|
|
337
433
|
消息最多 10 个附件,单个附件上限 20 MB、总量上限 50 MB,与 daemon 一致。
|
|
338
434
|
|
|
339
435
|
多模态 user 消息(附件、图片 `read_file` 回灌、中断通知)在历史与事件流中
|
|
340
|
-
一律使用
|
|
341
|
-
|
|
436
|
+
一律使用 `{"image": ...}` / `{"text": ...}` 原生部件并保持字段格式一致;仅在
|
|
437
|
+
向模型发起 chat-completions 请求的边界处转换为
|
|
342
438
|
OpenAI 风格的 `image_url` 部件。`--attach` 传 URL 时 `image` 直接记录该
|
|
343
|
-
URL
|
|
344
|
-
|
|
439
|
+
URL(模型服务端会自行下载;恢复历史上下文时要求该 URL 仍可访问);本地文件
|
|
440
|
+
没有可引用的 URL,`image` 存自包含的 base64
|
|
345
441
|
data-URI。
|
|
346
442
|
|
|
347
443
|
`stream-json` 每行一个 JSON 对象。`start`、`message`、`result` 事件中的
|
|
@@ -355,7 +451,12 @@ data-URI。
|
|
|
355
451
|
|
|
356
452
|
`assistant.delta` 实时提供 content、reasoning 与 tool-call 参数碎片;
|
|
357
453
|
`model.start`、`model.complete`、`model.retry`、`tool.start`、`tool.complete`
|
|
358
|
-
标记阶段。最后的 `result`
|
|
454
|
+
标记阶段。最后的 `result` 带完整消息。
|
|
455
|
+
|
|
456
|
+
Headless 会向模型提供 `present_file`,以保持生成轨迹与 Arena 工具契约一致。
|
|
457
|
+
该工具在 headless 中只校验目标是 workspace 内已有文件,并返回
|
|
458
|
+
`{"path":"<原始路径>","status":"success"}`;不会连接前端或打开 viewer。
|
|
459
|
+
自动打开 viewer 仅由 daemon/WebUI 消费同一工具结果后触发。
|
|
359
460
|
|
|
360
461
|
`ask_user` 只有在注入 handler 时才会提供给模型。TUI 和 WebUI 使用真人交互
|
|
361
462
|
handler;headless(`-p`)默认仍不开放该工具,但可配置远程 User Agent handler:
|
|
@@ -399,8 +500,9 @@ arena tui --workspace . --model mock/ask-user --session-id my-session
|
|
|
399
500
|
workspace 默认是启动命令时的当前目录(可用 `--workspace` 覆盖)。TUI 会把
|
|
400
501
|
实际 workspace root 和 cwd 动态注入 system prompt 与工具 schema;因此本机
|
|
401
502
|
运行时使用本机路径,部署进沙箱后会自然使用沙箱内的实际路径,不需要切换模式。
|
|
402
|
-
TUI
|
|
403
|
-
|
|
503
|
+
TUI 会向模型提供 `present_file`,以保持生成轨迹与 Arena 工具契约一致。由于
|
|
504
|
+
TUI 没有内置文件 viewer,该工具只校验 workspace 内的目标文件并返回 canonical
|
|
505
|
+
成功结果,不会打开文件;模型仍会在正文中报告生成文件的实际路径。
|
|
404
506
|
|
|
405
507
|
assistant 的 reasoning、正文和工具调用状态会边生成边输出。每轮结束都会把
|
|
406
508
|
完整消息原子写入与 headless、daemon 相同的 `history.json`;再次传入相同的
|
|
@@ -472,6 +574,17 @@ for await (const event of session.stream({ input: "设计一个网站" })) {
|
|
|
472
574
|
}
|
|
473
575
|
```
|
|
474
576
|
|
|
577
|
+
如果用户选择跳过问题,可提交结构化响应;这会写入
|
|
578
|
+
`{"answers":[],"skipped":true}` 并继续当前 turn,不会像 `cancel()` 那样
|
|
579
|
+
中断 turn:
|
|
580
|
+
|
|
581
|
+
```ts
|
|
582
|
+
await session.respondToInput(request.requestId, {
|
|
583
|
+
answers: [],
|
|
584
|
+
skipped: true,
|
|
585
|
+
});
|
|
586
|
+
```
|
|
587
|
+
|
|
475
588
|
持久连接、恢复和取消分别使用:
|
|
476
589
|
|
|
477
590
|
```ts
|
|
@@ -542,7 +655,7 @@ workspace,可设置 `ARENA_SESSION_WORKSPACE_MODE=empty`。
|
|
|
542
655
|
| `GET /api/chat/sessions/:id/messages` | 恢复完整消息历史 |
|
|
543
656
|
| `POST /api/chat/sessions/:id/retry` | 从最后一个失败模型节点继续,不追加 user 消息 |
|
|
544
657
|
| `POST /api/chat/sessions/:id/uploads` | 上传当前消息的附件 |
|
|
545
|
-
| `POST /api/chat/sessions/:id/input-response` |
|
|
658
|
+
| `POST /api/chat/sessions/:id/input-response` | 回答或跳过 `ask_user` |
|
|
546
659
|
| `POST /api/chat/sessions/:id/cancel` | 取消当前 turn |
|
|
547
660
|
| `POST /api/chat/sessions/:id/undo` | 回滚最近完成的 turn,并返回原输入 |
|
|
548
661
|
| `GET /api/chat/sessions/:id/workspace/:path` | 鉴权获取该 session 的 workspace 文件 |
|
|
@@ -577,6 +690,13 @@ part 放入实时消息。每个文件最大 20 MB,每条消息最多 10 个
|
|
|
577
690
|
SSE 支持 `Last-Event-ID` 断线续传。`ask_user` 会暂停同一个 Agent Promise;
|
|
578
691
|
用户提交答案后生成标准 `role=tool` 消息并继续循环。
|
|
579
692
|
|
|
693
|
+
Session SSE 会原样透传 `model.start`、`model.retry`、`model.complete` 和
|
|
694
|
+
`compaction` 生命周期事件。`model.complete.usage` 是当前模型请求的用量;
|
|
695
|
+
压缩摘要不会进入消息历史,其用量只存在于 `compaction.usage`。WebUI 同时通过
|
|
696
|
+
`data-agent-status` 显示模型重试和上下文压缩状态。收到 `model.retry` 时,客户端
|
|
697
|
+
应丢弃该次模型请求在此前产生的 reasoning、text 和 tool-call delta;重试后的
|
|
698
|
+
增量会从干净状态重新开始。
|
|
699
|
+
|
|
580
700
|
模型自动重试耗尽时,daemon 会把 `history.json` 保持在该模型调用之前的最后
|
|
581
701
|
一个完整 checkpoint,并将对应的历史哈希和失败元数据原子记录到
|
|
582
702
|
`model-retry.json`;消息内容仍以 `history.json` 为唯一真相源。手动重试只重新
|
|
@@ -628,7 +748,7 @@ curl -N -X POST \
|
|
|
628
748
|
|
|
629
749
|
## 工具
|
|
630
750
|
|
|
631
|
-
|
|
751
|
+
消息与工具契约配置保存在:
|
|
632
752
|
|
|
633
753
|
- `spec/message.json`
|
|
634
754
|
- `spec/tools.json`
|
|
@@ -637,14 +757,56 @@ curl -N -X POST \
|
|
|
637
757
|
`spec/` 目录,运行时也不依赖仓库文件。执行工具前仍使用 AJV 校验原始
|
|
638
758
|
Draft-07 schema。repo mode 的动态提示词模板保存在 `src/prompts.ts`:
|
|
639
759
|
|
|
640
|
-
`bash`、`ask_user`、`edit_file`、`read_file`、`fetch_page
|
|
641
|
-
`write_file`、`image_search`、`present_file`、`
|
|
642
|
-
`generate_speech`。
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
`
|
|
760
|
+
`bash`、`ask_user`、`add_voice`、`edit_file`、`read_file`、`fetch_page`、
|
|
761
|
+
`web_search`、`write_file`、`image_search`、`present_file`、`stop_process`、
|
|
762
|
+
`start_process`、`generate_image`、`generate_speech`、`get_process_output`。
|
|
763
|
+
|
|
764
|
+
新版生产导出的前 50 条脱敏请求单独保存在
|
|
765
|
+
[`tasks/v2`](tasks/v2/README.md),没有与原有 replay 数据混放。该目录记录了
|
|
766
|
+
2 GB 源文件的 SHA-256、全量解析统计、tool schema 变体和可重复执行的拆分命令;
|
|
767
|
+
`npm run refresh:arena-v2-contract` 用它刷新 canonical prompt/tool fixtures 并重新
|
|
768
|
+
生成 `src/canonical-data.ts`。
|
|
769
|
+
|
|
770
|
+
`bash` 只用于一次性命令:超时结果为 `status=timeout`,被信号终止为
|
|
771
|
+
`status=killed`,并会清理命令遗留的后台进程。需要跨 tool call 存活的 server、
|
|
772
|
+
watcher 或任务应使用 `start_process`;随后可用 `get_process_output` 按日志、端口
|
|
773
|
+
或退出状态阻塞等待,并用 `stop_process` 停止整个进程组。完整合并日志保存在
|
|
774
|
+
工作区的 `.arena/processes/`,工具返回对应的 `log_tail`;`stop_process` 对齐生产
|
|
775
|
+
只返回最后 100 行。assistant tool call 和这些 JSON tool result 会原样写入
|
|
776
|
+
`history.json`,供后续 turn replay。`start_process` 在 E2B 环境中还会用
|
|
777
|
+
`E2B_SANDBOX_ID` 组成 `{port}-{sandboxId}.e2b.app`,分别探测本地 Host 和用户
|
|
778
|
+
预览 Host;如果新开的公网端口仅拒绝后者,结果会按需增加 `warnings`。其他预览
|
|
779
|
+
代理可用 `ARENA_PREVIEW_HOST_TEMPLATE` 配置 Host 模板。没有告警时不返回该字段,
|
|
780
|
+
保持普通捕获的结果 shape 不变。
|
|
781
|
+
|
|
782
|
+
`web_search` 使用 Routify 网关提供的 Brave LLM Context,从工作区 `.env`
|
|
783
|
+
读取 `ROUTIFY_API_KEY`,默认通过内置的 ModelRouter 兼容接口调用
|
|
784
|
+
`brave.llm-context` 路由。实现按 depth 请求最多 3/5/8 条结果,并将
|
|
785
|
+
`grounding.generic` 的内容片段及 `sources` 的来源信息转换成 Arena 的既有工具
|
|
786
|
+
结果。请求固定考虑最多 20 个搜索候选,再通过 `maximum_number_of_urls` 将
|
|
787
|
+
最终来源数限制为 3/5/8。depth 还分别对应 1024/3072/8192 的总 token 预算和
|
|
788
|
+
512/552/2048 的单 URL token 预算;description 使用预算内的全部 grounding
|
|
789
|
+
snippets,仅在没有 grounding 内容时回退到来源摘要。三个 Code Arena 模式
|
|
790
|
+
使用独立的模式参数:来源数 3/5/10、总 token 预算 1280/4096/6144、单 URL
|
|
791
|
+
token 预算 512/1280/1536。
|
|
792
|
+
可用 `ROUTIFY_WEB_SEARCH_URL` 和 `ARENA_WEB_SEARCH_MODEL` 覆盖默认值。
|
|
793
|
+
|
|
794
|
+
`image_search` 使用 Routify 网关提供的 Brave Images Search,同样读取
|
|
795
|
+
`ROUTIFY_API_KEY`,通过 `X-Subscription-Token` 发送 GET 请求。默认使用内置的
|
|
796
|
+
ModelRouter 兼容接口,可用 `ROUTIFY_IMAGE_SEARCH_URL` 覆盖。实现优先下载 Brave
|
|
797
|
+
返回的原图地址,原图不可用
|
|
798
|
+
时回退到 Brave 代理缩略图,并保持既有工具结果格式和工作区文件命名不变。
|
|
799
|
+
|
|
800
|
+
Arena 的 `fetch_page` 和 Code Arena 的 `web_fetch` 默认仍使用本地抓取与正文
|
|
801
|
+
解析。设置 `CODE_HARNESS_ROUTIFY_WEB_FETCH_ENABLED=true` 后,两者改走 Routify
|
|
802
|
+
页面读取接口,并在首选读取服务不可用时使用备用服务;两者都失败则返回普通工具
|
|
803
|
+
错误。`fetch_page` 仍按 8000 字符分块并缓存同一 URL 的后续 chunk。认证复用
|
|
804
|
+
`ROUTIFY_API_KEY`。
|
|
805
|
+
|
|
806
|
+
`generate_image`、`generate_speech` 使用 ModelRouter/Routify,并从工作区
|
|
807
|
+
`.env` 读取同一个 `ROUTIFY_API_KEY`。图片使用 Google 兼容协议调用;可用
|
|
808
|
+
`ROUTIFY_VERTEX_BASE_URL` 覆盖默认根地址。语音使用 ModelRouter 的火山引擎
|
|
809
|
+
`/protocol/volcengine/api/v1/tts` 路由,不需要新增服务密钥。
|
|
648
810
|
|
|
649
811
|
`fetch_page` 使用 Defuddle 将 HTML 正文转换为 Markdown,并使用
|
|
650
812
|
`pdf-parse` 提取 PDF 的前 30 页。响应按 Markdown 边界稳定分块,同一轮内
|
|
@@ -659,11 +821,19 @@ Draft-07 schema。repo mode 的动态提示词模板保存在 `src/prompts.ts`
|
|
|
659
821
|
内容继续发送给模型。所有工具结果另有 1,000,000 字符的最终兜底。当前不做
|
|
660
822
|
OCR,扫描版 PDF 只会返回无可提取文字的提示。
|
|
661
823
|
|
|
662
|
-
|
|
663
|
-
`ARENA_IMAGE_MODEL`、`ARENA_SPEECH_MODEL`
|
|
824
|
+
图片和语音的默认 ModelRouter 路由分别为 `gemini-2.5-flash-image` 和
|
|
825
|
+
`doubao-tts`,可用 `ARENA_IMAGE_MODEL`、`ARENA_SPEECH_MODEL` 覆盖。图片生成结果和
|
|
664
826
|
搜索到的图片会立即下载到工作区;每次图片搜索的结果按生产命名保存为
|
|
665
827
|
`image-search/<query slug>-<序号>.<扩展名>`,并作为可预览文件显示在 Web UI。
|
|
666
|
-
|
|
828
|
+
语音生成先由 `add_voice` 生成两个试听候选并让用户选择,选择结果注册为稳定的
|
|
829
|
+
`voice_id`;后续 `generate_speech` 必须传入该 id。
|
|
830
|
+
无交互 handler 的 headless 模式仍会开放 `add_voice`,但不会生成无法播放的试听;
|
|
831
|
+
它会按语言和 `voice_identity` 确定性注册一个默认音色,并在结果中以
|
|
832
|
+
`virtual: true` 标记。返回的 `voice_id` 可直接用于后续 `generate_speech`。
|
|
833
|
+
也可用
|
|
834
|
+
`ARENA_SPEECH_VOICE` 强制覆盖底层音色。豆包响应中的 Base64 数据已经是 MP3、RIFF/WAV
|
|
835
|
+
或 Ogg Opus;`.ogg` 与 `.opus` 都保存 Ogg Opus 数据,所有支持的输出均不依赖
|
|
836
|
+
本地 `ffmpeg` 或 `lame`。
|
|
667
837
|
|
|
668
838
|
所有路径工具都限制在 `--workspace` 内并检查符号链接逃逸。`bash` 是本机
|
|
669
839
|
子进程,不是操作系统安全沙箱;多租户或不可信模型部署应使用容器或 VM。
|
|
@@ -679,4 +849,7 @@ npm test
|
|
|
679
849
|
```
|
|
680
850
|
|
|
681
851
|
测试覆盖消息契约、工具校验、headless、`/query`、实时双通道、
|
|
682
|
-
`ask_user`、`present_file` 和 daemon 优雅退出。
|
|
852
|
+
`ask_user`、`add_voice`、后台进程工具、`present_file` 和 daemon 优雅退出。
|
|
853
|
+
配置 `.env` 中的 `ROUTIFY_API_KEY` 后,可运行
|
|
854
|
+
`npm run verify:live-speech-voices` 对 headless `add_voice` 到真实
|
|
855
|
+
`generate_speech` 的多音色链路做烟测。
|
package/dist/agent.d.ts
CHANGED
|
@@ -2,16 +2,17 @@ import { type ArenaConfig } from "./config.js";
|
|
|
2
2
|
import { EventSink } from "./protocol.js";
|
|
3
3
|
import { type HarnessMode } from "./mode.js";
|
|
4
4
|
import { ToolExecutor } from "./tools.js";
|
|
5
|
-
import type { AgentResult, AskUserHandler, ClientContext, Message, ModelClient, RepoContext, UserTurnMessage, WorkspaceContext } from "./types.js";
|
|
5
|
+
import type { AgentResult, AskUserHandler, ClientContext, Message, ModelClient, RepoContext, ToolDefinition, UserTurnMessage, WorkspaceContext } from "./types.js";
|
|
6
6
|
interface AgentOptions {
|
|
7
7
|
client?: ModelClient;
|
|
8
8
|
tools?: ToolExecutor;
|
|
9
9
|
askUserHandler?: AskUserHandler;
|
|
10
10
|
sessionId?: string;
|
|
11
|
+
sessionAffinityId?: string;
|
|
11
12
|
signal?: AbortSignal;
|
|
12
13
|
clientContext?: ClientContext;
|
|
13
14
|
workspaceContext?: WorkspaceContext;
|
|
14
|
-
onCheckpoint?: (messages: readonly Message[]) => Promise<void>;
|
|
15
|
+
onCheckpoint?: (messages: readonly Message[], tools: readonly ToolDefinition[]) => Promise<void>;
|
|
15
16
|
onModelFailure?: (messages: readonly Message[], error: unknown) => void;
|
|
16
17
|
}
|
|
17
18
|
interface AgentRunOptions {
|
|
@@ -27,6 +28,7 @@ export declare class Agent {
|
|
|
27
28
|
private readonly client;
|
|
28
29
|
private readonly tools;
|
|
29
30
|
private readonly workspaceContext?;
|
|
31
|
+
private readonly sessionAffinityId;
|
|
30
32
|
readonly sessionId: string;
|
|
31
33
|
constructor(config: ArenaConfig, sink: EventSink, options?: AgentOptions);
|
|
32
34
|
run(prompt: string, history?: Message[], runOptions?: AgentRunOptions): Promise<AgentResult>;
|