@qwen-code/arena-agent 0.0.9-dev.23 → 0.0.9-dev.24
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 +9 -10
- package/README.md +12 -9
- package/dist/cli.js +0 -0
- package/dist/code-cli.js +0 -0
- package/dist/code-tools.js +14 -160
- package/dist/code-tools.js.map +1 -1
- package/dist/model-router-media.d.ts +21 -0
- package/dist/model-router-media.js +298 -0
- package/dist/model-router-media.js.map +1 -0
- package/dist/tools.js +66 -193
- package/dist/tools.js.map +1 -1
- package/dist/web/app.d.ts +1 -0
- package/package.json +1 -1
- package/dist/audit.d.ts +0 -14
- package/dist/audit.js +0 -31
- package/dist/audit.js.map +0 -1
- package/dist/dashscope.d.ts +0 -5
- package/dist/dashscope.js +0 -55
- package/dist/dashscope.js.map +0 -1
- package/dist/fetch-page/aparat.d.ts +0 -30
- package/dist/fetch-page/aparat.js +0 -209
- package/dist/fetch-page/aparat.js.map +0 -1
- package/dist/fetch-page/json-path.d.ts +0 -12
- package/dist/fetch-page/json-path.js +0 -111
- package/dist/fetch-page/json-path.js.map +0 -1
- package/dist/fetch-page/sites.d.ts +0 -26
- package/dist/fetch-page/sites.js +0 -39
- package/dist/fetch-page/sites.js.map +0 -1
- package/dist/fetch-page/text.d.ts +0 -5
- package/dist/fetch-page/text.js +0 -38
- package/dist/fetch-page/text.js.map +0 -1
- package/dist/fetch-page/types.d.ts +0 -17
- package/dist/fetch-page/types.js +0 -3
- package/dist/fetch-page/types.js.map +0 -1
- package/dist/fetch-page/youtube.d.ts +0 -35
- package/dist/fetch-page/youtube.js +0 -282
- package/dist/fetch-page/youtube.js.map +0 -1
- package/dist/web-search.d.ts +0 -5
- package/dist/web-search.js +0 -465
- package/dist/web-search.js.map +0 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
const defaultVertexBaseUrl = "https://routify-pub.alibaba-inc.com/protocol/vertex/v1beta";
|
|
4
|
+
const maximumGeneratedFileBytes = 25 * 1024 * 1024;
|
|
5
|
+
const maximumJsonResponseBytes = 35 * 1024 * 1024;
|
|
6
|
+
function record(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
8
|
+
? value
|
|
9
|
+
: {};
|
|
10
|
+
}
|
|
11
|
+
function stringValue(value) {
|
|
12
|
+
return typeof value === "string" ? value : "";
|
|
13
|
+
}
|
|
14
|
+
function modelRouterApiKey() {
|
|
15
|
+
const apiKey = process.env.ROUTIFY_API_KEY?.trim();
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
throw new Error("ModelRouter media tools require ROUTIFY_API_KEY");
|
|
18
|
+
}
|
|
19
|
+
return apiKey.replace(/^Bearer\s+/i, "");
|
|
20
|
+
}
|
|
21
|
+
function vertexModelUrl(model) {
|
|
22
|
+
const baseUrl = (process.env.ROUTIFY_VERTEX_BASE_URL || defaultVertexBaseUrl).replace(/\/+$/, "");
|
|
23
|
+
return `${baseUrl}/models/${encodeURIComponent(model)}:generateContent`;
|
|
24
|
+
}
|
|
25
|
+
function retryableStatus(status) {
|
|
26
|
+
return status === 408 || status === 409 || status === 429 || status >= 500;
|
|
27
|
+
}
|
|
28
|
+
function retryDelayMilliseconds(response, attempt) {
|
|
29
|
+
const retryAfter = Number(response.headers.get("retry-after"));
|
|
30
|
+
if (Number.isFinite(retryAfter) && retryAfter >= 0) {
|
|
31
|
+
return Math.min(60_000, retryAfter * 1000);
|
|
32
|
+
}
|
|
33
|
+
return Math.min(30_000, 2_000 * 2 ** attempt);
|
|
34
|
+
}
|
|
35
|
+
function responseDetail(payload, rawBody) {
|
|
36
|
+
return (stringValue(record(payload.routify_response).error_message) ||
|
|
37
|
+
stringValue(record(payload.error).message) ||
|
|
38
|
+
stringValue(payload.message) ||
|
|
39
|
+
stringValue(payload.detailMessage) ||
|
|
40
|
+
rawBody ||
|
|
41
|
+
"unknown provider error");
|
|
42
|
+
}
|
|
43
|
+
async function modelRouterFetch(url, init, label) {
|
|
44
|
+
const headers = new Headers(init.headers);
|
|
45
|
+
headers.set("x-goog-api-key", `Bearer ${modelRouterApiKey()}`);
|
|
46
|
+
const configuredRetries = Number(process.env.ROUTIFY_MEDIA_MAX_RETRIES ||
|
|
47
|
+
process.env.CODE_HARNESS_TOOL_MAX_RETRIES ||
|
|
48
|
+
5);
|
|
49
|
+
const maximumRetries = Number.isSafeInteger(configuredRetries) && configuredRetries >= 0
|
|
50
|
+
? configuredRetries
|
|
51
|
+
: 5;
|
|
52
|
+
for (let attempt = 0;; attempt += 1) {
|
|
53
|
+
const response = await fetch(url, { ...init, headers });
|
|
54
|
+
if (response.ok)
|
|
55
|
+
return response;
|
|
56
|
+
const rawBody = await response.text();
|
|
57
|
+
let payload = {};
|
|
58
|
+
try {
|
|
59
|
+
payload = record(JSON.parse(rawBody));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Keep the raw response body as the diagnostic.
|
|
63
|
+
}
|
|
64
|
+
const retryable = retryableStatus(response.status);
|
|
65
|
+
if (!retryable || attempt >= maximumRetries) {
|
|
66
|
+
throw new Error(`${label} failed (${response.status} ${response.statusText}): ${responseDetail(payload, rawBody).slice(0, 2000)}`);
|
|
67
|
+
}
|
|
68
|
+
await delay(retryDelayMilliseconds(response, attempt), undefined, {
|
|
69
|
+
signal: init.signal || undefined,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function responseBytes(response, limit = maximumGeneratedFileBytes) {
|
|
74
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
75
|
+
if (bytes.length > limit) {
|
|
76
|
+
throw new Error(`generated file exceeds ${limit} bytes`);
|
|
77
|
+
}
|
|
78
|
+
return bytes;
|
|
79
|
+
}
|
|
80
|
+
function parseJsonResponse(bytes, label) {
|
|
81
|
+
try {
|
|
82
|
+
return record(JSON.parse(bytes.toString("utf8")));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
throw new Error(`${label} returned malformed JSON`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function inlineDataFromResponse(payload, label, expectedMimePrefix) {
|
|
89
|
+
const candidates = Array.isArray(payload.candidates)
|
|
90
|
+
? payload.candidates
|
|
91
|
+
: [];
|
|
92
|
+
for (const candidate of candidates) {
|
|
93
|
+
const parts = Array.isArray(record(record(candidate).content).parts)
|
|
94
|
+
? record(record(candidate).content).parts
|
|
95
|
+
: [];
|
|
96
|
+
for (const part of parts) {
|
|
97
|
+
const inlineData = record(record(part).inlineData);
|
|
98
|
+
const mimeType = stringValue(inlineData.mimeType).toLowerCase();
|
|
99
|
+
const data = stringValue(inlineData.data);
|
|
100
|
+
if (!data || !mimeType.startsWith(expectedMimePrefix))
|
|
101
|
+
continue;
|
|
102
|
+
const bytes = Buffer.from(data, "base64");
|
|
103
|
+
if (bytes.length > maximumGeneratedFileBytes) {
|
|
104
|
+
throw new Error(`generated file exceeds ${maximumGeneratedFileBytes} bytes`);
|
|
105
|
+
}
|
|
106
|
+
return { bytes, mimeType };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`${label} response did not include ${expectedMimePrefix} data`);
|
|
110
|
+
}
|
|
111
|
+
const imageAspectRatios = [
|
|
112
|
+
["1:1", 1],
|
|
113
|
+
["2:3", 2 / 3],
|
|
114
|
+
["3:2", 3 / 2],
|
|
115
|
+
["3:4", 3 / 4],
|
|
116
|
+
["4:3", 4 / 3],
|
|
117
|
+
["4:5", 4 / 5],
|
|
118
|
+
["5:4", 5 / 4],
|
|
119
|
+
["9:16", 9 / 16],
|
|
120
|
+
["16:9", 16 / 9],
|
|
121
|
+
["21:9", 21 / 9],
|
|
122
|
+
];
|
|
123
|
+
function geminiImageConfig(size) {
|
|
124
|
+
const match = size.replace("*", "x").match(/^(\d+)x(\d+)$/i);
|
|
125
|
+
const width = Number(match?.[1] || 1024);
|
|
126
|
+
const height = Number(match?.[2] || 1024);
|
|
127
|
+
const ratio = width > 0 && height > 0 ? width / height : 1;
|
|
128
|
+
const [aspectRatio] = imageAspectRatios.reduce((best, candidate) => Math.abs(Math.log(candidate[1] / ratio)) <
|
|
129
|
+
Math.abs(Math.log(best[1] / ratio))
|
|
130
|
+
? candidate
|
|
131
|
+
: best);
|
|
132
|
+
const maximumDimension = Math.max(width, height);
|
|
133
|
+
const imageSize = maximumDimension > 2048
|
|
134
|
+
? "4K"
|
|
135
|
+
: maximumDimension > 1024
|
|
136
|
+
? "2K"
|
|
137
|
+
: "1K";
|
|
138
|
+
return { aspectRatio, imageSize };
|
|
139
|
+
}
|
|
140
|
+
export async function generateImageWithModelRouter(options) {
|
|
141
|
+
const parts = [{ text: options.prompt }];
|
|
142
|
+
for (const image of options.images || []) {
|
|
143
|
+
parts.push({
|
|
144
|
+
inlineData: {
|
|
145
|
+
mimeType: image.mimeType,
|
|
146
|
+
data: image.bytes.toString("base64"),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const response = await modelRouterFetch(vertexModelUrl(options.model), {
|
|
151
|
+
method: "POST",
|
|
152
|
+
headers: { "content-type": "application/json" },
|
|
153
|
+
body: JSON.stringify({
|
|
154
|
+
contents: [{ role: "user", parts }],
|
|
155
|
+
generationConfig: {
|
|
156
|
+
responseModalities: ["IMAGE"],
|
|
157
|
+
imageConfig: geminiImageConfig(options.size),
|
|
158
|
+
},
|
|
159
|
+
}),
|
|
160
|
+
signal: options.signal,
|
|
161
|
+
}, "generate_image");
|
|
162
|
+
const payload = parseJsonResponse(await responseBytes(response, maximumJsonResponseBytes), "generate_image");
|
|
163
|
+
return inlineDataFromResponse(payload, "generate_image", "image/").bytes;
|
|
164
|
+
}
|
|
165
|
+
function waveFromPcm(pcm, sampleRate, channels) {
|
|
166
|
+
const header = Buffer.alloc(44);
|
|
167
|
+
const bitsPerSample = 16;
|
|
168
|
+
const blockAlign = (channels * bitsPerSample) / 8;
|
|
169
|
+
header.write("RIFF", 0, "ascii");
|
|
170
|
+
header.writeUInt32LE(36 + pcm.length, 4);
|
|
171
|
+
header.write("WAVE", 8, "ascii");
|
|
172
|
+
header.write("fmt ", 12, "ascii");
|
|
173
|
+
header.writeUInt32LE(16, 16);
|
|
174
|
+
header.writeUInt16LE(1, 20);
|
|
175
|
+
header.writeUInt16LE(channels, 22);
|
|
176
|
+
header.writeUInt32LE(sampleRate, 24);
|
|
177
|
+
header.writeUInt32LE(sampleRate * blockAlign, 28);
|
|
178
|
+
header.writeUInt16LE(blockAlign, 32);
|
|
179
|
+
header.writeUInt16LE(bitsPerSample, 34);
|
|
180
|
+
header.write("data", 36, "ascii");
|
|
181
|
+
header.writeUInt32LE(pcm.length, 40);
|
|
182
|
+
return Buffer.concat([header, pcm]);
|
|
183
|
+
}
|
|
184
|
+
function pcmFormatFromMimeType(mimeType) {
|
|
185
|
+
const sampleRate = Number(mimeType.match(/rate=(\d+)/i)?.[1] || 24000);
|
|
186
|
+
const channels = Number(mimeType.match(/channels=(\d+)/i)?.[1] || 1);
|
|
187
|
+
return {
|
|
188
|
+
sampleRate: Number.isSafeInteger(sampleRate) && sampleRate > 0
|
|
189
|
+
? sampleRate
|
|
190
|
+
: 24000,
|
|
191
|
+
channels: Number.isSafeInteger(channels) && channels > 0 ? channels : 1,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async function runEncoder(command, arguments_, input, signal) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const child = spawn(command, arguments_, {
|
|
197
|
+
signal,
|
|
198
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
199
|
+
});
|
|
200
|
+
const stdout = [];
|
|
201
|
+
const stderr = [];
|
|
202
|
+
let outputBytes = 0;
|
|
203
|
+
let settled = false;
|
|
204
|
+
const finish = (error, output) => {
|
|
205
|
+
if (settled)
|
|
206
|
+
return;
|
|
207
|
+
settled = true;
|
|
208
|
+
if (error)
|
|
209
|
+
reject(error);
|
|
210
|
+
else
|
|
211
|
+
resolve(output);
|
|
212
|
+
};
|
|
213
|
+
child.stdout.on("data", (chunk) => {
|
|
214
|
+
outputBytes += chunk.length;
|
|
215
|
+
if (outputBytes > maximumGeneratedFileBytes) {
|
|
216
|
+
child.kill("SIGKILL");
|
|
217
|
+
finish(new Error(`generated file exceeds ${maximumGeneratedFileBytes} bytes`));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
stdout.push(chunk);
|
|
221
|
+
});
|
|
222
|
+
child.stderr.on("data", (chunk) => {
|
|
223
|
+
if (Buffer.concat(stderr).length < 4096)
|
|
224
|
+
stderr.push(chunk);
|
|
225
|
+
});
|
|
226
|
+
child.stdin.on("error", () => undefined);
|
|
227
|
+
child.on("error", (error) => {
|
|
228
|
+
if (error.code === "ENOENT")
|
|
229
|
+
finish(undefined, undefined);
|
|
230
|
+
else
|
|
231
|
+
finish(error);
|
|
232
|
+
});
|
|
233
|
+
child.on("close", (code) => {
|
|
234
|
+
if (settled)
|
|
235
|
+
return;
|
|
236
|
+
if (code === 0)
|
|
237
|
+
finish(undefined, Buffer.concat(stdout));
|
|
238
|
+
else {
|
|
239
|
+
finish(new Error(`${command} audio conversion failed (${code}): ${Buffer.concat(stderr)
|
|
240
|
+
.toString("utf8")
|
|
241
|
+
.slice(0, 1000)}`));
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
child.stdin.end(input);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
async function encodeWave(wave, format, signal) {
|
|
248
|
+
if (format === "wav")
|
|
249
|
+
return wave;
|
|
250
|
+
const ffmpegArguments = [
|
|
251
|
+
"-hide_banner",
|
|
252
|
+
"-loglevel",
|
|
253
|
+
"error",
|
|
254
|
+
"-i",
|
|
255
|
+
"pipe:0",
|
|
256
|
+
...(format === "opus" ? ["-c:a", "libopus"] : []),
|
|
257
|
+
"-f",
|
|
258
|
+
format,
|
|
259
|
+
"pipe:1",
|
|
260
|
+
];
|
|
261
|
+
const ffmpeg = await runEncoder("ffmpeg", ffmpegArguments, wave, signal);
|
|
262
|
+
if (ffmpeg)
|
|
263
|
+
return ffmpeg;
|
|
264
|
+
if (format === "mp3") {
|
|
265
|
+
const lame = await runEncoder("lame", ["--silent", "-", "-"], wave, signal);
|
|
266
|
+
if (lame)
|
|
267
|
+
return lame;
|
|
268
|
+
}
|
|
269
|
+
throw new Error(`Gemini TTS ${format} output requires ffmpeg${format === "mp3" ? " or lame" : ""}; use a .wav output path or install an encoder`);
|
|
270
|
+
}
|
|
271
|
+
export async function generateSpeechWithModelRouter(options) {
|
|
272
|
+
const response = await modelRouterFetch(vertexModelUrl(options.model), {
|
|
273
|
+
method: "POST",
|
|
274
|
+
headers: { "content-type": "application/json" },
|
|
275
|
+
body: JSON.stringify({
|
|
276
|
+
contents: [
|
|
277
|
+
{
|
|
278
|
+
role: "user",
|
|
279
|
+
parts: [{ text: options.text }],
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
generationConfig: {
|
|
283
|
+
responseModalities: ["AUDIO"],
|
|
284
|
+
speechConfig: {
|
|
285
|
+
voiceConfig: {
|
|
286
|
+
prebuiltVoiceConfig: { voiceName: options.voice },
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
signal: options.signal,
|
|
292
|
+
}, "generate_speech");
|
|
293
|
+
const payload = parseJsonResponse(await responseBytes(response, maximumJsonResponseBytes), "generate_speech");
|
|
294
|
+
const audio = inlineDataFromResponse(payload, "generate_speech", "audio/");
|
|
295
|
+
const { sampleRate, channels } = pcmFormatFromMimeType(audio.mimeType);
|
|
296
|
+
return encodeWave(waveFromPcm(audio.bytes, sampleRate, channels), options.format, options.signal);
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=model-router-media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-router-media.js","sourceRoot":"","sources":["../src/model-router-media.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.js
CHANGED
|
@@ -2,7 +2,6 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { existsSync, mkdirSync, realpathSync, } from "node:fs";
|
|
3
3
|
import { open, readFile, realpath, stat, writeFile, } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { setTimeout as delay } from "node:timers/promises";
|
|
6
5
|
import { Ajv } from "ajv";
|
|
7
6
|
import addFormats from "ajv-formats";
|
|
8
7
|
import { detect as detectEncoding } from "chardet";
|
|
@@ -17,6 +16,7 @@ import { FetchPageReader } from "./fetch-page.js";
|
|
|
17
16
|
import { prepareImageForModel } from "./image.js";
|
|
18
17
|
import { imageTextFromFallbackModel } from "./image-input-fallback.js";
|
|
19
18
|
import { isCodeArenaMode } from "./mode.js";
|
|
19
|
+
import { generateImageWithModelRouter, generateSpeechWithModelRouter, } from "./model-router-media.js";
|
|
20
20
|
import { HttpModelClient } from "./provider.js";
|
|
21
21
|
import { RoutifyFetchPageReader, routifyWebFetchEnabled, } from "./routify-web-fetch.js";
|
|
22
22
|
import { toolDefinitions } from "./spec.js";
|
|
@@ -361,58 +361,6 @@ function record(value) {
|
|
|
361
361
|
function stringValue(value) {
|
|
362
362
|
return typeof value === "string" ? value : "";
|
|
363
363
|
}
|
|
364
|
-
function dashScopeApiKey() {
|
|
365
|
-
const apiKey = process.env.DASHSCOPE_API_KEY;
|
|
366
|
-
if (!apiKey) {
|
|
367
|
-
throw new Error("DashScope tools require DASHSCOPE_API_KEY");
|
|
368
|
-
}
|
|
369
|
-
return apiKey;
|
|
370
|
-
}
|
|
371
|
-
function dashScopeRoot() {
|
|
372
|
-
return (process.env.DASHSCOPE_API_BASE ||
|
|
373
|
-
process.env.DASHSCOPE_BASE_URL ||
|
|
374
|
-
"https://dashscope.aliyuncs.com")
|
|
375
|
-
.replace(/\/+$/, "")
|
|
376
|
-
.replace(/\/(?:api\/v1|compatible-mode\/v1)$/i, "");
|
|
377
|
-
}
|
|
378
|
-
function dashScopeUrl(protocol, pathname) {
|
|
379
|
-
const prefix = protocol === "api" ? "/api/v1" : "/compatible-mode/v1";
|
|
380
|
-
const normalized = pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
381
|
-
return `${dashScopeRoot()}${prefix}${normalized}`;
|
|
382
|
-
}
|
|
383
|
-
async function dashScopeFetch(protocol, pathname, init, label) {
|
|
384
|
-
const headers = new Headers(init.headers);
|
|
385
|
-
headers.set("authorization", `Bearer ${dashScopeApiKey()}`);
|
|
386
|
-
const response = await fetch(dashScopeUrl(protocol, pathname), {
|
|
387
|
-
...init,
|
|
388
|
-
headers,
|
|
389
|
-
});
|
|
390
|
-
if (response.ok)
|
|
391
|
-
return response;
|
|
392
|
-
const body = await response.text();
|
|
393
|
-
let detail = body;
|
|
394
|
-
try {
|
|
395
|
-
const payload = record(JSON.parse(body));
|
|
396
|
-
detail =
|
|
397
|
-
stringValue(payload.message) ||
|
|
398
|
-
stringValue(record(payload.error).message) ||
|
|
399
|
-
body;
|
|
400
|
-
}
|
|
401
|
-
catch {
|
|
402
|
-
// Keep the response text as the diagnostic.
|
|
403
|
-
}
|
|
404
|
-
throw new Error(`${label} failed (${response.status} ${response.statusText}): ${detail.slice(0, 2000)}`);
|
|
405
|
-
}
|
|
406
|
-
async function dashScopeJson(protocol, pathname, init, label) {
|
|
407
|
-
const response = await dashScopeFetch(protocol, pathname, init, label);
|
|
408
|
-
return record(await response.json());
|
|
409
|
-
}
|
|
410
|
-
function responseMessage(payload) {
|
|
411
|
-
return (stringValue(payload.message) ||
|
|
412
|
-
stringValue(record(payload.output).message) ||
|
|
413
|
-
stringValue(payload.code) ||
|
|
414
|
-
"unknown provider error");
|
|
415
|
-
}
|
|
416
364
|
async function responseBytes(response, limit = 4 * 1024 * 1024) {
|
|
417
365
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
418
366
|
if (bytes.length > limit) {
|
|
@@ -1019,9 +967,8 @@ class ArenaToolExecutor {
|
|
|
1019
967
|
throw new Error("file_path must end in .jpg, .jpeg, or .png");
|
|
1020
968
|
}
|
|
1021
969
|
mkdirSync(path.dirname(target), { recursive: true });
|
|
1022
|
-
const model = process.env.ARENA_IMAGE_MODEL || "
|
|
1023
|
-
const
|
|
1024
|
-
const content = [];
|
|
970
|
+
const model = process.env.ARENA_IMAGE_MODEL || "gemini-2.5-flash-image";
|
|
971
|
+
const references = [];
|
|
1025
972
|
for (const imagePath of images || []) {
|
|
1026
973
|
const source = await this.confinedPath(imagePath);
|
|
1027
974
|
const extension = path.extname(source).toLowerCase();
|
|
@@ -1033,96 +980,19 @@ class ArenaToolExecutor {
|
|
|
1033
980
|
if (bytes.length > 20 * 1024 * 1024) {
|
|
1034
981
|
throw new Error(`reference image exceeds 20 MB: ${imagePath}`);
|
|
1035
982
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
983
|
+
references.push({
|
|
984
|
+
bytes,
|
|
985
|
+
fileName: path.basename(source),
|
|
986
|
+
mimeType,
|
|
1038
987
|
});
|
|
1039
988
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
watermark: false,
|
|
1045
|
-
};
|
|
1046
|
-
if (isQwenImage2) {
|
|
1047
|
-
parameters.prompt_extend = true;
|
|
1048
|
-
}
|
|
1049
|
-
else {
|
|
1050
|
-
parameters.n = 1;
|
|
1051
|
-
if (!images?.length)
|
|
1052
|
-
parameters.thinking_mode = true;
|
|
1053
|
-
}
|
|
1054
|
-
const headers = {
|
|
1055
|
-
"content-type": "application/json",
|
|
1056
|
-
};
|
|
1057
|
-
if (!isQwenImage2)
|
|
1058
|
-
headers["x-dashscope-async"] = "enable";
|
|
1059
|
-
const submitted = await dashScopeJson("api", isQwenImage2
|
|
1060
|
-
? "/services/aigc/multimodal-generation/generation"
|
|
1061
|
-
: "/services/aigc/image-generation/generation", {
|
|
1062
|
-
method: "POST",
|
|
1063
|
-
headers,
|
|
1064
|
-
body: JSON.stringify({
|
|
1065
|
-
model,
|
|
1066
|
-
input: {
|
|
1067
|
-
messages: [{ role: "user", content }],
|
|
1068
|
-
},
|
|
1069
|
-
parameters,
|
|
1070
|
-
}),
|
|
989
|
+
await writeFile(target, await generateImageWithModelRouter({
|
|
990
|
+
images: references,
|
|
991
|
+
model,
|
|
992
|
+
prompt,
|
|
1071
993
|
signal: this.signal,
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
? submitted
|
|
1075
|
-
: undefined;
|
|
1076
|
-
if (!isQwenImage2) {
|
|
1077
|
-
const taskId = stringValue(record(submitted.output).task_id);
|
|
1078
|
-
if (!taskId) {
|
|
1079
|
-
throw new Error(`generate_image returned no task_id: ${responseMessage(submitted)}`);
|
|
1080
|
-
}
|
|
1081
|
-
const timeoutMs = Number(process.env.DASHSCOPE_TASK_TIMEOUT_MS || 5 * 60 * 1000);
|
|
1082
|
-
const pollIntervalMs = Number(process.env.DASHSCOPE_TASK_POLL_INTERVAL_MS || 1000);
|
|
1083
|
-
const deadline = Date.now() + timeoutMs;
|
|
1084
|
-
while (Date.now() <= deadline) {
|
|
1085
|
-
const task = await dashScopeJson("api", `/tasks/${encodeURIComponent(taskId)}`, { method: "GET", signal: this.signal }, "generate_image status");
|
|
1086
|
-
const output = record(task.output);
|
|
1087
|
-
const taskStatus = stringValue(output.task_status).toUpperCase();
|
|
1088
|
-
if (taskStatus === "SUCCEEDED") {
|
|
1089
|
-
completed = task;
|
|
1090
|
-
break;
|
|
1091
|
-
}
|
|
1092
|
-
if (["FAILED", "CANCELED", "UNKNOWN"].includes(taskStatus)) {
|
|
1093
|
-
throw new Error(`generate_image task ${taskStatus}: ${responseMessage(task)}`);
|
|
1094
|
-
}
|
|
1095
|
-
if (Date.now() + pollIntervalMs > deadline)
|
|
1096
|
-
break;
|
|
1097
|
-
await delay(pollIntervalMs, undefined, { signal: this.signal });
|
|
1098
|
-
}
|
|
1099
|
-
if (!completed) {
|
|
1100
|
-
throw new Error(`generate_image timed out waiting for task ${taskId}`);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
if (!completed) {
|
|
1104
|
-
throw new Error("generate_image returned no response");
|
|
1105
|
-
}
|
|
1106
|
-
const output = record(completed.output);
|
|
1107
|
-
const choices = Array.isArray(output.choices) ? output.choices : [];
|
|
1108
|
-
const message = record(record(choices[0]).message);
|
|
1109
|
-
const generatedContent = Array.isArray(message.content)
|
|
1110
|
-
? message.content
|
|
1111
|
-
: [];
|
|
1112
|
-
const generated = generatedContent
|
|
1113
|
-
.map(record)
|
|
1114
|
-
.find((item) => typeof item.image === "string");
|
|
1115
|
-
const legacyResults = Array.isArray(output.results) ? output.results : [];
|
|
1116
|
-
const imageUrl = stringValue(generated?.image) ||
|
|
1117
|
-
stringValue(record(legacyResults[0]).url);
|
|
1118
|
-
if (!imageUrl) {
|
|
1119
|
-
throw new Error("generate_image response did not include an image URL");
|
|
1120
|
-
}
|
|
1121
|
-
const imageResponse = await fetch(imageUrl, { signal: this.signal });
|
|
1122
|
-
if (!imageResponse.ok) {
|
|
1123
|
-
throw new Error(`image download failed (${imageResponse.status})`);
|
|
1124
|
-
}
|
|
1125
|
-
await writeFile(target, await responseBytes(imageResponse, 25 * 1024 * 1024));
|
|
994
|
+
size: process.env.ARENA_IMAGE_SIZE || "1024*1024",
|
|
995
|
+
}));
|
|
1126
996
|
return {
|
|
1127
997
|
status: "success",
|
|
1128
998
|
file_path: this.relativePath(target),
|
|
@@ -1137,65 +1007,68 @@ class ArenaToolExecutor {
|
|
|
1137
1007
|
".opus": "opus",
|
|
1138
1008
|
}[extension];
|
|
1139
1009
|
if (!format) {
|
|
1140
|
-
throw new Error("
|
|
1010
|
+
throw new Error("ModelRouter speech output supports .mp3, .wav, or .opus");
|
|
1141
1011
|
}
|
|
1142
1012
|
mkdirSync(path.dirname(target), { recursive: true });
|
|
1143
|
-
const model = process.env.ARENA_SPEECH_MODEL || "
|
|
1013
|
+
const model = process.env.ARENA_SPEECH_MODEL || "gemini-3.1-flash-tts-preview";
|
|
1144
1014
|
const feminine = voiceIdentity.gender !== "masculine";
|
|
1145
1015
|
const primaryLanguage = language.toLowerCase().split(/[-_]/)[0] || "";
|
|
1146
|
-
const
|
|
1016
|
+
const geminiTts = /^gemini-.*-tts(?:-|$)/i.test(model);
|
|
1017
|
+
const voices = geminiTts
|
|
1147
1018
|
? feminine
|
|
1148
|
-
? [
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1019
|
+
? [
|
|
1020
|
+
"Kore",
|
|
1021
|
+
"Aoede",
|
|
1022
|
+
"Zephyr",
|
|
1023
|
+
"Leda",
|
|
1024
|
+
"Callirrhoe",
|
|
1025
|
+
"Autonoe",
|
|
1026
|
+
"Despina",
|
|
1027
|
+
"Erinome",
|
|
1028
|
+
"Laomedeia",
|
|
1029
|
+
"Achernar",
|
|
1030
|
+
"Gacrux",
|
|
1031
|
+
"Pulcherrima",
|
|
1032
|
+
"Vindemiatrix",
|
|
1033
|
+
"Sulafat",
|
|
1034
|
+
]
|
|
1035
|
+
: [
|
|
1036
|
+
"Puck",
|
|
1037
|
+
"Charon",
|
|
1038
|
+
"Fenrir",
|
|
1039
|
+
"Orus",
|
|
1040
|
+
"Enceladus",
|
|
1041
|
+
"Iapetus",
|
|
1042
|
+
"Umbriel",
|
|
1043
|
+
"Algieba",
|
|
1044
|
+
"Algenib",
|
|
1045
|
+
"Rasalgethi",
|
|
1046
|
+
"Alnilam",
|
|
1047
|
+
"Schedar",
|
|
1048
|
+
"Achird",
|
|
1049
|
+
"Zubenelgenubi",
|
|
1050
|
+
"Sadachbia",
|
|
1051
|
+
"Sadaltager",
|
|
1052
|
+
]
|
|
1053
|
+
: primaryLanguage === "en"
|
|
1054
|
+
? feminine
|
|
1055
|
+
? ["loongeva_v3.6", "longanhuan_v3.6"]
|
|
1056
|
+
: ["loongjohn", "longjielidou_v3.6"]
|
|
1057
|
+
: feminine
|
|
1058
|
+
? ["longanhuan_v3.6"]
|
|
1059
|
+
: ["longjielidou_v3.6"];
|
|
1153
1060
|
const requestedIndex = Math.max(0, Math.trunc(Number(voiceIdentity.index || 0)));
|
|
1154
|
-
const voice = process.env.
|
|
1061
|
+
const voice = process.env.ARENA_SPEECH_VOICE ||
|
|
1155
1062
|
voices[requestedIndex % voices.length] ||
|
|
1156
|
-
voices[0]
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
"de",
|
|
1160
|
-
"en",
|
|
1161
|
-
"es",
|
|
1162
|
-
"fil",
|
|
1163
|
-
"fr",
|
|
1164
|
-
"id",
|
|
1165
|
-
"it",
|
|
1166
|
-
"ja",
|
|
1167
|
-
"ko",
|
|
1168
|
-
"ms",
|
|
1169
|
-
"pt",
|
|
1170
|
-
"ru",
|
|
1171
|
-
"th",
|
|
1172
|
-
"vi",
|
|
1173
|
-
"zh",
|
|
1174
|
-
]);
|
|
1175
|
-
const input = {
|
|
1176
|
-
text,
|
|
1177
|
-
voice,
|
|
1063
|
+
voices[0] ||
|
|
1064
|
+
(geminiTts ? "Kore" : "longanhuan_v3.6");
|
|
1065
|
+
await writeFile(target, await generateSpeechWithModelRouter({
|
|
1178
1066
|
format,
|
|
1179
|
-
|
|
1180
|
-
};
|
|
1181
|
-
if (supportedHints.has(primaryLanguage)) {
|
|
1182
|
-
input.language_hints = [primaryLanguage];
|
|
1183
|
-
}
|
|
1184
|
-
const payload = await dashScopeJson("api", "/services/audio/tts/SpeechSynthesizer", {
|
|
1185
|
-
method: "POST",
|
|
1186
|
-
headers: { "content-type": "application/json" },
|
|
1187
|
-
body: JSON.stringify({ model, input }),
|
|
1067
|
+
model,
|
|
1188
1068
|
signal: this.signal,
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
throw new Error(`generate_speech returned no audio URL: ${responseMessage(payload)}`);
|
|
1193
|
-
}
|
|
1194
|
-
const audioResponse = await fetch(audioUrl, { signal: this.signal });
|
|
1195
|
-
if (!audioResponse.ok) {
|
|
1196
|
-
throw new Error(`audio download failed (${audioResponse.status})`);
|
|
1197
|
-
}
|
|
1198
|
-
await writeFile(target, await responseBytes(audioResponse, 25 * 1024 * 1024));
|
|
1069
|
+
text,
|
|
1070
|
+
voice,
|
|
1071
|
+
}));
|
|
1199
1072
|
return {
|
|
1200
1073
|
status: "success",
|
|
1201
1074
|
file_path: this.relativePath(target),
|