@qwen-code/arena-agent 0.0.9-dev.8 → 0.0.9-image-input-fallback.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 +22 -8
- package/README.md +80 -10
- package/dist/agent.js +33 -9
- package/dist/agent.js.map +1 -1
- package/dist/anthropic.js +16 -8
- 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/audit.d.ts +14 -0
- package/dist/audit.js +31 -0
- package/dist/audit.js.map +1 -0
- 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/cli.js +25 -10
- package/dist/cli.js.map +1 -1
- package/dist/code-tools.d.ts +0 -5
- package/dist/code-tools.js +11 -192
- package/dist/code-tools.js.map +1 -1
- package/dist/config.d.ts +8 -0
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/dashscope.d.ts +5 -0
- package/dist/dashscope.js +55 -0
- package/dist/dashscope.js.map +1 -0
- package/dist/fetch-page/aparat.d.ts +30 -0
- package/dist/fetch-page/aparat.js +209 -0
- package/dist/fetch-page/aparat.js.map +1 -0
- package/dist/fetch-page/json-path.d.ts +12 -0
- package/dist/fetch-page/json-path.js +111 -0
- package/dist/fetch-page/json-path.js.map +1 -0
- package/dist/fetch-page/sites.d.ts +26 -0
- package/dist/fetch-page/sites.js +39 -0
- package/dist/fetch-page/sites.js.map +1 -0
- package/dist/fetch-page/text.d.ts +5 -0
- package/dist/fetch-page/text.js +38 -0
- package/dist/fetch-page/text.js.map +1 -0
- package/dist/fetch-page/types.d.ts +17 -0
- package/dist/fetch-page/types.js +3 -0
- package/dist/fetch-page/types.js.map +1 -0
- package/dist/fetch-page/youtube.d.ts +35 -0
- package/dist/fetch-page/youtube.js +282 -0
- package/dist/fetch-page/youtube.js.map +1 -0
- 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/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 +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/model-diagnostics.js +5 -2
- package/dist/model-diagnostics.js.map +1 -1
- package/dist/provider.js +33 -14
- 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 +1 -0
- package/dist/server.js +75 -3
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +2 -1
- package/dist/tools.js +91 -104
- package/dist/tools.js.map +1 -1
- package/dist/tui.d.ts +1 -0
- package/dist/tui.js +3 -0
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +10 -6
- package/dist/web/app.js +59 -6
- package/dist/web/app.js.map +1 -1
- package/dist/web-search.d.ts +5 -0
- package/dist/web-search.js +465 -0
- package/dist/web-search.js.map +1 -0
- package/docs/BINARY_DISTRIBUTION.md +25 -18
- package/docs/MODES_AND_RELEASES.md +8 -4
- package/docs/SDK.md +24 -1
- package/package.json +16 -3
- package/web/styles.css +22 -7
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import { dashScopeFetch, dashScopeJson, record, stringValue, } from "./dashscope.js";
|
|
2
|
+
// 每个可覆盖的默认值只写一次:审计记录和真正的调用必须读同一个来源,
|
|
3
|
+
// 否则 result.json 会记下一个从未被使用过的模型。
|
|
4
|
+
const webSearchModel = () => process.env.ARENA_WEB_SEARCH_MODEL || "qwen-plus";
|
|
5
|
+
const responsesWebSearchModel = () => process.env.ARENA_WEB_SEARCH_RESPONSES_MODEL || "qwen3.7-plus";
|
|
6
|
+
export const selectedWebSearchModel = () => webSearchBackend() === "responses"
|
|
7
|
+
? responsesWebSearchModel()
|
|
8
|
+
: webSearchModel();
|
|
9
|
+
export function webSearchBackend() {
|
|
10
|
+
const value = process.env.ARENA_WEB_SEARCH_BACKEND || "enable_search";
|
|
11
|
+
if (value === "enable_search" || value === "responses")
|
|
12
|
+
return value;
|
|
13
|
+
throw new Error('ARENA_WEB_SEARCH_BACKEND must be "enable_search" or "responses"');
|
|
14
|
+
}
|
|
15
|
+
function webSearchLimit(depth) {
|
|
16
|
+
return { "1": 3, "2": 5, "3": 8 }[depth] || 5;
|
|
17
|
+
}
|
|
18
|
+
// 摘要长度目标按源轨迹的 description 字符数分布锚定(中位数 depth1≈966、
|
|
19
|
+
// depth2≈1796、depth3≈2151),对应 spec 里 depth 越高摘录越详细的契约。
|
|
20
|
+
function descriptionTarget(depth) {
|
|
21
|
+
return { "1": "700-1300", "2": "1200-2200", "3": "1500-3000" }[depth] || "1200-2200";
|
|
22
|
+
}
|
|
23
|
+
function validHttpUrl(value) {
|
|
24
|
+
if (typeof value !== "string")
|
|
25
|
+
return false;
|
|
26
|
+
try {
|
|
27
|
+
const parsed = new URL(value);
|
|
28
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 比较用的规范化键:URL 解析器已经统一了大小写主机名、默认端口和空路径,
|
|
36
|
+
* 逐字节比较则会把 `https://EXAMPLE.test:443/a` 和 `https://example.test/a`
|
|
37
|
+
* 判成两个来源(误拒),又把 `https://example.test` 和同名带斜杠的当成两条
|
|
38
|
+
* 不同结果(漏判重复)。只用于比较,对外输出仍是模型给的原始 URL。
|
|
39
|
+
* 不放宽到「只比域名」:那会让同站任意页面互相冒充。
|
|
40
|
+
*
|
|
41
|
+
* fragment 不参与:它根本不会发给服务器,`/page#one` 与 `/page#two` 取到的是
|
|
42
|
+
* 同一份内容——留着它既会误拒同源抽取,又能靠换 fragment 绕过结果查重。
|
|
43
|
+
*/
|
|
44
|
+
function urlKey(value) {
|
|
45
|
+
const parsed = new URL(value);
|
|
46
|
+
parsed.hash = "";
|
|
47
|
+
return parsed.href;
|
|
48
|
+
}
|
|
49
|
+
function responsesWebSearchPrompt(query, depth, limit) {
|
|
50
|
+
return `Implement a bounded web_search backend for the query below.
|
|
51
|
+
|
|
52
|
+
QUERY:
|
|
53
|
+
${query}
|
|
54
|
+
|
|
55
|
+
TOOL BUDGET:
|
|
56
|
+
- Call web_search exactly once with the QUERY verbatim.
|
|
57
|
+
- Do not rewrite, retry, or issue follow-up searches.
|
|
58
|
+
- After that search, call web_extractor at most once with no more than ${limit} selected URLs.
|
|
59
|
+
- Do not make any additional web_search or web_extractor calls.
|
|
60
|
+
|
|
61
|
+
RESULT CONTRACT:
|
|
62
|
+
- Return at most ${limit} highly relevant results. This is a hard ceiling, not a target.
|
|
63
|
+
- Stop at the relevance boundary; do not fill the quota with weak matches or duplicates.
|
|
64
|
+
- If no exact match exists but the search found topical pages, return only the single closest topical result.
|
|
65
|
+
- Preserve provider relevance order and source language.
|
|
66
|
+
- Every result must contain sequential id values starting at 1, an HTTP(S) url, a non-empty original title, and a non-empty source-grounded description.
|
|
67
|
+
- Keep each description focused on query-relevant extracted evidence; target ${descriptionTarget(depth)} characters and use less when the source exposes less relevant content.
|
|
68
|
+
- Include pageAge only when supported by a source date or age.
|
|
69
|
+
|
|
70
|
+
Submit the result only through emit_web_search_results. Do not emit a normal assistant message.`;
|
|
71
|
+
}
|
|
72
|
+
function responsesWebSearchEmitter(limit) {
|
|
73
|
+
return {
|
|
74
|
+
type: "function",
|
|
75
|
+
name: "emit_web_search_results",
|
|
76
|
+
description: "Submit final source-grounded web search results after the bounded search workflow.",
|
|
77
|
+
parameters: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {
|
|
80
|
+
status: { type: "string", enum: ["success"] },
|
|
81
|
+
results: {
|
|
82
|
+
type: "array",
|
|
83
|
+
minItems: 1,
|
|
84
|
+
maxItems: limit,
|
|
85
|
+
items: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
id: { type: "integer" },
|
|
89
|
+
url: { type: "string" },
|
|
90
|
+
title: { type: "string" },
|
|
91
|
+
description: { type: "string" },
|
|
92
|
+
pageAge: { type: "string" },
|
|
93
|
+
},
|
|
94
|
+
required: ["id", "url", "title", "description"],
|
|
95
|
+
additionalProperties: false,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ["status", "results"],
|
|
100
|
+
additionalProperties: false,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function parseResponsesEvents(body) {
|
|
105
|
+
const events = [];
|
|
106
|
+
for (const block of body.replaceAll("\r\n", "\n").split(/\n\n+/)) {
|
|
107
|
+
const data = block
|
|
108
|
+
.split("\n")
|
|
109
|
+
.filter((line) => line.startsWith("data:"))
|
|
110
|
+
.map((line) => line.slice(5).replace(/^ /, ""))
|
|
111
|
+
.join("\n");
|
|
112
|
+
if (!data || data === "[DONE]")
|
|
113
|
+
continue;
|
|
114
|
+
try {
|
|
115
|
+
events.push(record(JSON.parse(data)));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
throw new Error("Responses web_search returned malformed SSE data");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!events.length) {
|
|
122
|
+
throw new Error("Responses web_search returned no SSE events");
|
|
123
|
+
}
|
|
124
|
+
return events;
|
|
125
|
+
}
|
|
126
|
+
/** 单条 message 自己的 output_text。跨 message 不再拼接——见下方说明。 */
|
|
127
|
+
function messageOutputText(item) {
|
|
128
|
+
return (Array.isArray(item.content) ? item.content : [])
|
|
129
|
+
.map(record)
|
|
130
|
+
.filter((part) => part.type === "output_text" && typeof part.text === "string")
|
|
131
|
+
.map((part) => stringValue(part.text))
|
|
132
|
+
.join("\n");
|
|
133
|
+
}
|
|
134
|
+
function parseJsonResult(raw) {
|
|
135
|
+
for (const candidate of [
|
|
136
|
+
raw,
|
|
137
|
+
raw.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, ""),
|
|
138
|
+
]) {
|
|
139
|
+
try {
|
|
140
|
+
return { parsed: true, value: JSON.parse(candidate) };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Try the optional Markdown-fence-stripped form.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return { parsed: false };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 采用哪一条结果,位置就必须来自同一条。
|
|
150
|
+
*
|
|
151
|
+
* 早先的实现把所有 message 的 output_text 拼在一起当内容,位置却取最后一条带
|
|
152
|
+
* output_text 的 message——包括空白的那条。于是「合法 JSON 在 search 之前、
|
|
153
|
+
* search 之后再补一条空消息」就能骗过顺序校验:JSON.parse 容忍尾部空白,拼接
|
|
154
|
+
* 后照样解析成功,而位置被那条空消息顶到了 evidence 之后。
|
|
155
|
+
*
|
|
156
|
+
* 现在的规则是:采用**最后一条非空 message**,并要求它自身就是合法 JSON。注意
|
|
157
|
+
* 这不是「从后往前找最后一条能解析的」——最后一条非空 message 解析不了就直接
|
|
158
|
+
* 失败,不回退到更早的那条。这是有意的 fail-closed:结果之后又冒出一段无法解析
|
|
159
|
+
* 的输出,说明这次响应的形状已经不是契约描述的样子,静默挑一条更早的来用,正是
|
|
160
|
+
* 这条路径最该避免的「安静降级」。跨 message 拼接(含把 closing fence 单独放到
|
|
161
|
+
* evidence 之后)同样不再被接受。
|
|
162
|
+
*/
|
|
163
|
+
function parseResponsesContract(items) {
|
|
164
|
+
const emitters = [];
|
|
165
|
+
const messages = [];
|
|
166
|
+
items.forEach((raw, index) => {
|
|
167
|
+
const item = record(raw);
|
|
168
|
+
if (item.type === "function_call" &&
|
|
169
|
+
item.name === "emit_web_search_results") {
|
|
170
|
+
emitters.push({ index, text: stringValue(item.arguments) });
|
|
171
|
+
}
|
|
172
|
+
else if (item.type === "message") {
|
|
173
|
+
const text = messageOutputText(item);
|
|
174
|
+
// 空白 message 不是结果,不参与采用,也不能顶替位置。
|
|
175
|
+
if (text.trim())
|
|
176
|
+
messages.push({ index, text });
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
// 预算违规先于内容解析:否则报「多个 emitter」还是「JSON 无效」,取决于最后
|
|
180
|
+
// 一个 emitter 的 arguments 是否恰好合法,同一种违规会有两种诊断。
|
|
181
|
+
if (emitters.length > 1) {
|
|
182
|
+
throw new Error("Responses web_search tool-budget violation: multiple result emitter calls");
|
|
183
|
+
}
|
|
184
|
+
const emitted = emitters[0];
|
|
185
|
+
const adopted = emitted && emitted.text.trim() ? emitted : messages.at(-1);
|
|
186
|
+
if (!adopted) {
|
|
187
|
+
throw new Error("Responses web_search returned no result object");
|
|
188
|
+
}
|
|
189
|
+
const result = parseJsonResult(adopted.text);
|
|
190
|
+
if (!result.parsed) {
|
|
191
|
+
throw new Error("Responses web_search result object is not valid JSON");
|
|
192
|
+
}
|
|
193
|
+
return { value: result.value, resultAt: adopted.index };
|
|
194
|
+
}
|
|
195
|
+
function validateResponsesResults(value, limit) {
|
|
196
|
+
const payload = record(value);
|
|
197
|
+
const errors = [];
|
|
198
|
+
if (Object.keys(payload).sort().join(",") !== "results,status" ||
|
|
199
|
+
payload.status !== "success") {
|
|
200
|
+
errors.push("invalid top-level contract");
|
|
201
|
+
}
|
|
202
|
+
const results = Array.isArray(payload.results) ? payload.results : [];
|
|
203
|
+
if (!Array.isArray(payload.results))
|
|
204
|
+
errors.push("results is not an array");
|
|
205
|
+
if (results.length < 1 || results.length > limit) {
|
|
206
|
+
errors.push(`result count must be between 1 and ${limit}`);
|
|
207
|
+
}
|
|
208
|
+
const seenUrls = new Set();
|
|
209
|
+
const normalized = results.map((value, index) => {
|
|
210
|
+
const result = record(value);
|
|
211
|
+
const number = index + 1;
|
|
212
|
+
const allowedKeys = new Set([
|
|
213
|
+
"id",
|
|
214
|
+
"url",
|
|
215
|
+
"title",
|
|
216
|
+
"description",
|
|
217
|
+
"pageAge",
|
|
218
|
+
]);
|
|
219
|
+
if (value === null ||
|
|
220
|
+
typeof value !== "object" ||
|
|
221
|
+
Array.isArray(value)) {
|
|
222
|
+
errors.push(`result ${number} is not an object`);
|
|
223
|
+
}
|
|
224
|
+
if (Object.keys(result).some((key) => !allowedKeys.has(key))) {
|
|
225
|
+
errors.push(`result ${number} has extra fields`);
|
|
226
|
+
}
|
|
227
|
+
if (!Number.isInteger(result.id) || result.id !== number) {
|
|
228
|
+
errors.push(`result ${number} has an invalid id`);
|
|
229
|
+
}
|
|
230
|
+
if (!validHttpUrl(result.url)) {
|
|
231
|
+
errors.push(`result ${number} has an invalid URL`);
|
|
232
|
+
}
|
|
233
|
+
else if (seenUrls.has(urlKey(result.url))) {
|
|
234
|
+
// 规范化后比较:同一页面的裸域名与带斜杠形式不能算两条结果。
|
|
235
|
+
errors.push(`result ${number} has a duplicate URL`);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
seenUrls.add(urlKey(result.url));
|
|
239
|
+
}
|
|
240
|
+
if (typeof result.title !== "string" || !result.title.trim()) {
|
|
241
|
+
errors.push(`result ${number} has an empty title`);
|
|
242
|
+
}
|
|
243
|
+
if (typeof result.description !== "string" ||
|
|
244
|
+
!result.description.trim()) {
|
|
245
|
+
errors.push(`result ${number} has an empty description`);
|
|
246
|
+
}
|
|
247
|
+
if ("pageAge" in result &&
|
|
248
|
+
(typeof result.pageAge !== "string" || !result.pageAge.trim())) {
|
|
249
|
+
errors.push(`result ${number} has an invalid pageAge`);
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
id: result.id,
|
|
253
|
+
url: result.url,
|
|
254
|
+
title: result.title,
|
|
255
|
+
description: result.description,
|
|
256
|
+
...(typeof result.pageAge === "string"
|
|
257
|
+
? { pageAge: result.pageAge }
|
|
258
|
+
: {}),
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
if (errors.length) {
|
|
262
|
+
throw new Error(`Responses web_search contract violation: ${errors.join("; ")}`);
|
|
263
|
+
}
|
|
264
|
+
return normalized;
|
|
265
|
+
}
|
|
266
|
+
export async function executeWebSearch(query, depth, signal) {
|
|
267
|
+
if (webSearchBackend() === "responses") {
|
|
268
|
+
return webSearchResponses(query, depth, signal);
|
|
269
|
+
}
|
|
270
|
+
return webSearchEnableSearch(query, depth, signal);
|
|
271
|
+
}
|
|
272
|
+
async function webSearchEnableSearch(query, depth, signal) {
|
|
273
|
+
const model = webSearchModel();
|
|
274
|
+
const searchStrategy = depth === "1" ? "turbo" : "max";
|
|
275
|
+
const payload = await dashScopeJson("api", "/services/aigc/text-generation/generation", {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: { "content-type": "application/json" },
|
|
278
|
+
body: JSON.stringify({
|
|
279
|
+
model,
|
|
280
|
+
input: {
|
|
281
|
+
messages: [{ role: "user", content: query }],
|
|
282
|
+
},
|
|
283
|
+
parameters: {
|
|
284
|
+
enable_search: true,
|
|
285
|
+
result_format: "message",
|
|
286
|
+
search_options: {
|
|
287
|
+
forced_search: true,
|
|
288
|
+
enable_source: true,
|
|
289
|
+
enable_citation: true,
|
|
290
|
+
citation_format: "[<number>]",
|
|
291
|
+
search_strategy: searchStrategy,
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
}),
|
|
295
|
+
signal,
|
|
296
|
+
}, "web_search");
|
|
297
|
+
const output = record(payload.output);
|
|
298
|
+
const searchInfo = record(output.search_info);
|
|
299
|
+
const searchResults = Array.isArray(searchInfo.search_results)
|
|
300
|
+
? searchInfo.search_results
|
|
301
|
+
: [];
|
|
302
|
+
const limit = webSearchLimit(depth);
|
|
303
|
+
// 参考轨迹条目:{id, url, title, description[, pageAge]};
|
|
304
|
+
// DashScope 无 pageAge,按可选键省略。
|
|
305
|
+
return {
|
|
306
|
+
status: "success",
|
|
307
|
+
results: searchResults.slice(0, limit).map((value, index) => {
|
|
308
|
+
const item = record(value);
|
|
309
|
+
return {
|
|
310
|
+
id: Number(item.index) || index + 1,
|
|
311
|
+
url: stringValue(item.url),
|
|
312
|
+
title: stringValue(item.title),
|
|
313
|
+
description: stringValue(item.content) ||
|
|
314
|
+
stringValue(item.snippet) ||
|
|
315
|
+
stringValue(item.summary),
|
|
316
|
+
};
|
|
317
|
+
}),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
async function webSearchResponses(query, depth, signal) {
|
|
321
|
+
const limit = webSearchLimit(depth);
|
|
322
|
+
const model = responsesWebSearchModel();
|
|
323
|
+
const response = await dashScopeFetch("compatible", "/responses", {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
"content-type": "application/json",
|
|
327
|
+
accept: "text/event-stream",
|
|
328
|
+
},
|
|
329
|
+
body: JSON.stringify({
|
|
330
|
+
model,
|
|
331
|
+
input: responsesWebSearchPrompt(query, depth, limit),
|
|
332
|
+
tools: [
|
|
333
|
+
{ type: "web_search" },
|
|
334
|
+
{ type: "web_extractor" },
|
|
335
|
+
responsesWebSearchEmitter(limit),
|
|
336
|
+
],
|
|
337
|
+
reasoning: { effort: "low" },
|
|
338
|
+
store: false,
|
|
339
|
+
stream: true,
|
|
340
|
+
}),
|
|
341
|
+
signal,
|
|
342
|
+
}, "Responses web_search");
|
|
343
|
+
const events = parseResponsesEvents(await response.text());
|
|
344
|
+
const completedEvent = [...events]
|
|
345
|
+
.reverse()
|
|
346
|
+
.find((event) => event.type === "response.completed");
|
|
347
|
+
if (!completedEvent) {
|
|
348
|
+
const failure = [...events]
|
|
349
|
+
.reverse()
|
|
350
|
+
.find((event) => event.type === "response.failed" || event.type === "error");
|
|
351
|
+
const failureResponse = record(failure?.response);
|
|
352
|
+
const detail = stringValue(record(failureResponse.error).message) ||
|
|
353
|
+
stringValue(record(failure?.error).message) ||
|
|
354
|
+
stringValue(failure?.message) ||
|
|
355
|
+
"response did not complete";
|
|
356
|
+
throw new Error(`Responses web_search failed: ${detail}`);
|
|
357
|
+
}
|
|
358
|
+
const completed = record(completedEvent.response);
|
|
359
|
+
if (completed.status !== "completed") {
|
|
360
|
+
const detail = stringValue(record(completed.error).message) ||
|
|
361
|
+
stringValue(completed.status) ||
|
|
362
|
+
"unknown response status";
|
|
363
|
+
throw new Error(`Responses web_search failed: ${detail}`);
|
|
364
|
+
}
|
|
365
|
+
if (!Array.isArray(completed.output)) {
|
|
366
|
+
throw new Error("Responses web_search returned no output items");
|
|
367
|
+
}
|
|
368
|
+
const items = completed.output.map(record);
|
|
369
|
+
const searches = items.filter((item) => item.type === "web_search_call");
|
|
370
|
+
const extractors = items.filter((item) => item.type === "web_extractor_call");
|
|
371
|
+
const searchQueries = searches.flatMap((item) => {
|
|
372
|
+
const action = record(item.action);
|
|
373
|
+
if (Array.isArray(action.queries)) {
|
|
374
|
+
return action.queries.filter((value) => typeof value === "string");
|
|
375
|
+
}
|
|
376
|
+
return typeof action.query === "string" ? [action.query] : [];
|
|
377
|
+
});
|
|
378
|
+
// 本次搜索报告的来源集合。结果 URL 与被抽取的 URL 都要以它接地,所以只算
|
|
379
|
+
// 一次,两处共用;比较一律走规范化键。
|
|
380
|
+
const sourceUrls = new Set(searches.flatMap((item) => {
|
|
381
|
+
const sources = record(item.action).sources;
|
|
382
|
+
return Array.isArray(sources)
|
|
383
|
+
? sources
|
|
384
|
+
.map((source) => record(source).url)
|
|
385
|
+
.filter(validHttpUrl)
|
|
386
|
+
.map(urlKey)
|
|
387
|
+
: [];
|
|
388
|
+
}));
|
|
389
|
+
const budgetErrors = [];
|
|
390
|
+
if (searches.length !== 1) {
|
|
391
|
+
budgetErrors.push("expected exactly one web_search call");
|
|
392
|
+
}
|
|
393
|
+
// 契约是 search → extractor:抽取必须发生在搜索之后,否则「抽取范围不越出
|
|
394
|
+
// 本次搜索」根本无从谈起(模型可以先抽任意站点,再补一次搜索)。只数不看
|
|
395
|
+
// 顺序就漏掉这条。
|
|
396
|
+
const firstSearchAt = items.findIndex((item) => item.type === "web_search_call");
|
|
397
|
+
const firstExtractorAt = items.findIndex((item) => item.type === "web_extractor_call");
|
|
398
|
+
if (firstExtractorAt !== -1 &&
|
|
399
|
+
(firstSearchAt === -1 || firstExtractorAt < firstSearchAt)) {
|
|
400
|
+
budgetErrors.push("web_extractor ran before web_search");
|
|
401
|
+
}
|
|
402
|
+
if (searchQueries.length !== 1 || searchQueries[0] !== query) {
|
|
403
|
+
budgetErrors.push("web_search query was not the single verbatim query");
|
|
404
|
+
}
|
|
405
|
+
if (extractors.length > 1) {
|
|
406
|
+
budgetErrors.push("expected at most one web_extractor call");
|
|
407
|
+
}
|
|
408
|
+
if (extractors.some((item) => Array.isArray(item.urls) && item.urls.length > limit)) {
|
|
409
|
+
budgetErrors.push(`web_extractor exceeded the ${limit}-URL limit`);
|
|
410
|
+
}
|
|
411
|
+
// urls 看不见就无法核对来源。形状不对(字符串、null、对象、混入非 HTTP(S)
|
|
412
|
+
// 条目)按契约违规处理:这条路径的全部价值就是可审计,静默放行等于假装校验过。
|
|
413
|
+
if (extractors.some((item) => !Array.isArray(item.urls) ||
|
|
414
|
+
item.urls.some((url) => !validHttpUrl(url)))) {
|
|
415
|
+
budgetErrors.push("web_extractor did not report an HTTP(S) URL list");
|
|
416
|
+
}
|
|
417
|
+
// 抽取出来的内容会成为结果的 description,所以限制条数还不够:被抽取的 URL
|
|
418
|
+
// 必须来自本次搜索报告的来源。否则模型可以从任意站点取正文,再挂到一个已经
|
|
419
|
+
// 接地的结果 URL 上,description 宣称的 source-grounded 就是空话。
|
|
420
|
+
//
|
|
421
|
+
// 这条规则的边界要说清楚:它保证「抽取范围不超出本次搜索」,不保证「每条
|
|
422
|
+
// description 出自它自己的 result URL」。搜索来源 [A,B]、抽取 B、只报 A 仍
|
|
423
|
+
// 会通过。收紧成「抽取 ⊆ 最终结果」是错的:prompt 明确要求先抽取再按相关性
|
|
424
|
+
// 收敛("Stop at the relevance boundary"),抽取多于返回是契约内行为。真正
|
|
425
|
+
// 的逐条溯源要在 emitter contract 里带 per-result citation,那是产品决定,
|
|
426
|
+
// 不在本次修复范围内。
|
|
427
|
+
// sourceUrls 为空是「provider 没报来源」,由下面专门的错误负责,这里不改判。
|
|
428
|
+
const ungroundedExtractions = sourceUrls.size
|
|
429
|
+
? extractors.flatMap((item) => Array.isArray(item.urls)
|
|
430
|
+
? item.urls.filter((url) => validHttpUrl(url) && !sourceUrls.has(urlKey(url)))
|
|
431
|
+
: [])
|
|
432
|
+
: [];
|
|
433
|
+
if (ungroundedExtractions.length) {
|
|
434
|
+
budgetErrors.push("web_extractor selected URLs web_search did not return: " +
|
|
435
|
+
ungroundedExtractions.join(", "));
|
|
436
|
+
}
|
|
437
|
+
if (budgetErrors.length) {
|
|
438
|
+
throw new Error(`Responses web_search tool-budget violation: ${budgetErrors.join("; ")}`);
|
|
439
|
+
}
|
|
440
|
+
// 多个 emitter 由 parseResponsesContract 在解析内容之前就拒掉。
|
|
441
|
+
const contract = parseResponsesContract(items);
|
|
442
|
+
// 证据必须先于结论:结果对象排在 search(以及 extractor,如果调了)之前,
|
|
443
|
+
// 说明 description 是先写好、再补一次能覆盖住 URL 的搜索——和 extractor 抢跑
|
|
444
|
+
// 是同一种事后追认,计数和 URL 归属都查不出来。两条取结果的路径(function
|
|
445
|
+
// emitter 与 fallback message)都按同一规则判。
|
|
446
|
+
if (contract.resultAt !== -1 &&
|
|
447
|
+
(contract.resultAt < firstSearchAt ||
|
|
448
|
+
(firstExtractorAt !== -1 && contract.resultAt < firstExtractorAt))) {
|
|
449
|
+
throw new Error("Responses web_search contract violation: results were emitted before the search evidence");
|
|
450
|
+
}
|
|
451
|
+
const results = validateResponsesResults(contract.value, limit);
|
|
452
|
+
if (!sourceUrls.size) {
|
|
453
|
+
// 与「结果 URL 不在来源里」区分开:这里是 provider 没有报告任何来源,
|
|
454
|
+
// 无法做接地校验,属于上游格式问题而不是模型编造。
|
|
455
|
+
throw new Error("Responses web_search contract violation: web_search reported no source URLs to ground the results");
|
|
456
|
+
}
|
|
457
|
+
const ungrounded = results
|
|
458
|
+
.map((result) => result.url)
|
|
459
|
+
.filter((url) => validHttpUrl(url) && !sourceUrls.has(urlKey(url)));
|
|
460
|
+
if (ungrounded.length) {
|
|
461
|
+
throw new Error(`Responses web_search contract violation: result URLs were not returned by web_search: ${ungrounded.join(", ")}`);
|
|
462
|
+
}
|
|
463
|
+
return { status: "success", results };
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.js","sourceRoot":"","sources":["../src/web-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Arena 可以使用 Node.js Single Executable Applications(SEA)构建为一个包含
|
|
4
4
|
Node.js 运行时、应用代码和静态资源的可执行文件。目标机器不需要安装 Node.js。
|
|
5
5
|
|
|
6
|
-
如果业务机只是受安装权限或 Node.js
|
|
7
|
-
|
|
8
|
-
|
|
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
9
|
|
|
10
10
|
## npm 安装(业务机有 Node.js 18)
|
|
11
11
|
|
|
@@ -39,13 +39,15 @@ npm 命令本身需要 Node.js。如果业务机连 Node.js 18 也没有,macOS
|
|
|
39
39
|
curl -fsSL https://cdn.jsdelivr.net/npm/@qwen-code/arena-cli@latest/install.sh | sh
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
跟随滚动更新的 dev 渠道并指定安装目录:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
curl -fsSL https://cdn.jsdelivr.net/npm/@qwen-code/arena-cli@dev/install.sh \
|
|
46
|
-
| sh -s -- --version
|
|
46
|
+
| sh -s -- --version dev --install-dir "$HOME/bin"
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
这里的两个 `dev` 都需要保留:前者选择安装脚本,后者选择对应平台二进制。
|
|
50
|
+
|
|
49
51
|
安装脚本检测 macOS/Linux、x64/arm64 与 Linux glibc/musl,从 npm 下载对应平台包,
|
|
50
52
|
校验 tarball checksum,并把 `arena` 安装到 `~/.local/bin`。如果该目录不在 PATH,
|
|
51
53
|
脚本会幂等更新当前 shell 的 profile;设置 `ARENA_NO_MODIFY_PATH=1` 可以关闭。
|
|
@@ -98,9 +100,10 @@ npm run package:binary
|
|
|
98
100
|
```
|
|
99
101
|
|
|
100
102
|
默认命令构建当前 runner 的系统、CPU 和 libc。CI 还支持在 Linux x64 上按 Node
|
|
101
|
-
SEA
|
|
102
|
-
|
|
103
|
-
|
|
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 二进制镜像下载,并校验对应的
|
|
104
107
|
`SHASUMS256.txt`,关闭 code cache/snapshot 后注入 SEA blob。
|
|
105
108
|
macOS 产物再使用固定版本和 checksum 的 `rcodesign` 做 ad-hoc 签名。Aone 从仓库的
|
|
106
109
|
`toolchains/apple-codesign-0.29.0` 工具链分支拉取固定 commit,避免构建时依赖 GitHub
|
|
@@ -129,8 +132,9 @@ node scripts/package-binaries.mjs \
|
|
|
129
132
|
```
|
|
130
133
|
|
|
131
134
|
CI 应构建并汇总 `build/npm/packages/<target>`。原生 Runtime 通常应在对应环境中
|
|
132
|
-
构建;禁用 SEA snapshot/code cache 后,`
|
|
133
|
-
Linux x64 Runner 上使用经过校验的目标 Node Runtime
|
|
135
|
+
构建;禁用 SEA snapshot/code cache 后,`linux-x64`、`linux-x64-musl` 和
|
|
136
|
+
`darwin-x64` 都可以在 Linux x64 Runner 上使用经过校验的目标 Node Runtime
|
|
137
|
+
组装。
|
|
134
138
|
|
|
135
139
|
本仓库使用 Aone CI,流水线定义在
|
|
136
140
|
[`/.aoneci/arena-binaries.yaml`](../.aoneci/arena-binaries.yaml)。当前项目没有关联
|
|
@@ -155,7 +159,8 @@ git push origin v0.0.10-dev.1
|
|
|
155
159
|
|
|
156
160
|
正式版同理,例如 `package.json` 为 `0.0.10` 时推送 `v0.0.10`,发布脚本会自动
|
|
157
161
|
使用 npm `latest` tag。Tag 名与版本不一致时发布步骤会直接失败,避免把错误版本
|
|
158
|
-
发布到 npm
|
|
162
|
+
发布到 npm。首次稳定版发布前请显式使用 `@dev` 或完整版本号;首个正式版本发布后
|
|
163
|
+
才把无版本安装渠道作为稳定入口。
|
|
159
164
|
|
|
160
165
|
Aone 官方不提供 Windows/macOS 托管资源;`darwin-x64` 已通过上述交叉构建覆盖。
|
|
161
166
|
Linux arm64 的两个平台包暂不参与自动发布,以免非关键 ARM64 Job 阻塞 x64
|
|
@@ -188,26 +193,28 @@ npm run publish:binaries -- \
|
|
|
188
193
|
|
|
189
194
|
## 平台与兼容性
|
|
190
195
|
|
|
191
|
-
SEA
|
|
196
|
+
SEA 产物内含目标平台的 Node.js 可执行文件,因此需要为每种目标分别构建:
|
|
192
197
|
|
|
193
198
|
- macOS arm64 与 x64
|
|
194
199
|
- Linux arm64/x64 的 glibc 与 musl
|
|
195
200
|
- Windows x64
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
除流水线已覆盖的三个关键 x64 目标外,其他目标应在对应操作系统和 CPU 架构的
|
|
203
|
+
构建机或 CI runner 上执行。
|
|
199
204
|
|
|
200
205
|
“业务机不需要 Node.js 20+”不等于“二进制不受 Node.js 20 的系统要求影响”。
|
|
201
206
|
SEA 把 Node.js 可执行文件放进 Arena,运行时仍由操作系统加载这个内嵌运行时:
|
|
202
207
|
|
|
203
|
-
-
|
|
208
|
+
- 当前 Linux x64 glibc 包的最低要求是 glibc 2.17;
|
|
204
209
|
- musl 包用于 Alpine 等 musl 系统,不能代替 glibc 包;
|
|
205
210
|
- 在较新的 Linux 上打包,不能自动获得对更老 glibc 的兼容性。
|
|
206
211
|
|
|
207
212
|
因此,业务机只有 Node.js 18 通常不是问题;真正需要确认的是它的操作系统、CPU
|
|
208
|
-
架构和 `ldd --version
|
|
209
|
-
|
|
210
|
-
|
|
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
|
+
下限。
|
|
211
218
|
|
|
212
219
|
单文件只消除了目标机器安装 Node.js 的要求,并不会内嵌所有外部程序:
|
|
213
220
|
|
|
@@ -110,10 +110,14 @@ npm run publish:binaries -- --dry-run
|
|
|
110
110
|
|
|
111
111
|
## 原 Code Harness 的迁移边界
|
|
112
112
|
|
|
113
|
-
迁入的是三种模式的运行时 contract
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
`tasks/code-
|
|
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。
|
|
117
121
|
|
|
118
122
|
只有在两组模式确实需要独立版本、独立依赖或不同发布权限时,才值得增加两个
|
|
119
123
|
很薄的入口包;即便如此,共享核心仍应留在本仓库,而不是复制实现。
|