@bunny-agent/daemon 0.9.28 → 0.9.29-beta.5
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/dist/bundle.mjs +343 -24
- package/dist/index.js +343 -24
- package/dist/nextjs.js +342 -24
- package/dist/routes/coding.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/nextjs.js
CHANGED
|
@@ -263368,18 +263368,139 @@ var generateImageSchema = {
|
|
|
263368
263368
|
required: ["prompt"],
|
|
263369
263369
|
additionalProperties: false
|
|
263370
263370
|
};
|
|
263371
|
-
async function resolveB64(item) {
|
|
263371
|
+
async function resolveB64(item, apiKey) {
|
|
263372
263372
|
if (item.b64_json)
|
|
263373
263373
|
return item.b64_json;
|
|
263374
|
-
if (item.
|
|
263375
|
-
|
|
263374
|
+
if (item.b64Json)
|
|
263375
|
+
return item.b64Json;
|
|
263376
|
+
if (item.image_base64)
|
|
263377
|
+
return item.image_base64;
|
|
263378
|
+
if (item.imageBase64)
|
|
263379
|
+
return item.imageBase64;
|
|
263380
|
+
if (item.base64)
|
|
263381
|
+
return item.base64;
|
|
263382
|
+
if (typeof item.image === "string")
|
|
263383
|
+
return item.image;
|
|
263384
|
+
if (item.image?.b64_json)
|
|
263385
|
+
return item.image.b64_json;
|
|
263386
|
+
if (item.image?.base64)
|
|
263387
|
+
return item.image.base64;
|
|
263388
|
+
const url = item.url ?? item.image_url ?? item.imageUrl ?? item.image?.url;
|
|
263389
|
+
if (url) {
|
|
263390
|
+
const headers = {};
|
|
263391
|
+
if (apiKey) {
|
|
263392
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
263393
|
+
}
|
|
263394
|
+
const res = await fetch(url, { headers });
|
|
263376
263395
|
if (res.ok)
|
|
263377
263396
|
return Buffer.from(await res.arrayBuffer()).toString("base64");
|
|
263378
263397
|
}
|
|
263379
263398
|
return void 0;
|
|
263380
263399
|
}
|
|
263381
|
-
|
|
263382
|
-
const
|
|
263400
|
+
function pickImageItem(response) {
|
|
263401
|
+
const tryFromObject = (value2) => {
|
|
263402
|
+
if (!value2 || typeof value2 !== "object")
|
|
263403
|
+
return void 0;
|
|
263404
|
+
const obj = value2;
|
|
263405
|
+
return {
|
|
263406
|
+
b64_json: obj.b64_json ?? obj.b64Json,
|
|
263407
|
+
b64Json: obj.b64Json,
|
|
263408
|
+
url: obj.url ?? obj.imageUrl,
|
|
263409
|
+
image_base64: obj.image_base64 ?? obj.imageBase64,
|
|
263410
|
+
imageBase64: obj.imageBase64,
|
|
263411
|
+
image_url: obj.image_url ?? obj.imageUrl,
|
|
263412
|
+
imageUrl: obj.imageUrl,
|
|
263413
|
+
base64: obj.base64,
|
|
263414
|
+
image: obj.image
|
|
263415
|
+
};
|
|
263416
|
+
};
|
|
263417
|
+
const asItem = (value2) => {
|
|
263418
|
+
if (value2 == null)
|
|
263419
|
+
return void 0;
|
|
263420
|
+
if (typeof value2 === "string") {
|
|
263421
|
+
return { base64: value2 };
|
|
263422
|
+
}
|
|
263423
|
+
if (typeof value2 === "object") {
|
|
263424
|
+
const normalized = tryFromObject(value2);
|
|
263425
|
+
if (normalized)
|
|
263426
|
+
return normalized;
|
|
263427
|
+
}
|
|
263428
|
+
return void 0;
|
|
263429
|
+
};
|
|
263430
|
+
const fromDataArray = Array.isArray(response.data) ? asItem(response.data[0]) : void 0;
|
|
263431
|
+
if (fromDataArray)
|
|
263432
|
+
return fromDataArray;
|
|
263433
|
+
const fromDataValue = asItem(response.data);
|
|
263434
|
+
if (fromDataValue)
|
|
263435
|
+
return fromDataValue;
|
|
263436
|
+
const responseRecord = response;
|
|
263437
|
+
const imagesValue = responseRecord.images;
|
|
263438
|
+
const outputValue = responseRecord.output;
|
|
263439
|
+
const fromImagesArray = Array.isArray(imagesValue) ? asItem(imagesValue[0]) : void 0;
|
|
263440
|
+
if (fromImagesArray)
|
|
263441
|
+
return fromImagesArray;
|
|
263442
|
+
const fromImagesValue = asItem(imagesValue);
|
|
263443
|
+
if (fromImagesValue)
|
|
263444
|
+
return fromImagesValue;
|
|
263445
|
+
const fromOutputArray = Array.isArray(outputValue) ? asItem(outputValue[0]) : void 0;
|
|
263446
|
+
if (fromOutputArray)
|
|
263447
|
+
return fromOutputArray;
|
|
263448
|
+
const fromOutputValue = asItem(outputValue);
|
|
263449
|
+
if (fromOutputValue)
|
|
263450
|
+
return fromOutputValue;
|
|
263451
|
+
const fromTopLevel = asItem(response);
|
|
263452
|
+
if (fromTopLevel)
|
|
263453
|
+
return fromTopLevel;
|
|
263454
|
+
const queue = [response];
|
|
263455
|
+
while (queue.length > 0) {
|
|
263456
|
+
const current = queue.shift();
|
|
263457
|
+
if (current == null)
|
|
263458
|
+
continue;
|
|
263459
|
+
if (typeof current === "string") {
|
|
263460
|
+
if (/^[A-Za-z0-9+/=]{32,}$/.test(current))
|
|
263461
|
+
return { base64: current };
|
|
263462
|
+
continue;
|
|
263463
|
+
}
|
|
263464
|
+
if (typeof current !== "object")
|
|
263465
|
+
continue;
|
|
263466
|
+
const normalized = tryFromObject(current);
|
|
263467
|
+
if (normalized) {
|
|
263468
|
+
const hasUsefulField = Boolean(normalized.b64_json ?? normalized.b64Json ?? normalized.image_base64 ?? normalized.imageBase64 ?? normalized.base64 ?? normalized.url ?? normalized.image_url ?? normalized.imageUrl ?? (typeof normalized.image === "string" ? normalized.image : normalized.image?.b64_json ?? normalized.image?.base64 ?? normalized.image?.url));
|
|
263469
|
+
if (hasUsefulField)
|
|
263470
|
+
return normalized;
|
|
263471
|
+
}
|
|
263472
|
+
if (Array.isArray(current)) {
|
|
263473
|
+
queue.push(...current);
|
|
263474
|
+
continue;
|
|
263475
|
+
}
|
|
263476
|
+
for (const value2 of Object.values(current)) {
|
|
263477
|
+
queue.push(value2);
|
|
263478
|
+
}
|
|
263479
|
+
}
|
|
263480
|
+
return {};
|
|
263481
|
+
}
|
|
263482
|
+
function detectImageMime(filePath) {
|
|
263483
|
+
const ext2 = extname2(filePath).toLowerCase();
|
|
263484
|
+
if (ext2 === ".jpg" || ext2 === ".jpeg")
|
|
263485
|
+
return "image/jpeg";
|
|
263486
|
+
if (ext2 === ".webp")
|
|
263487
|
+
return "image/webp";
|
|
263488
|
+
if (ext2 === ".gif")
|
|
263489
|
+
return "image/gif";
|
|
263490
|
+
return "image/png";
|
|
263491
|
+
}
|
|
263492
|
+
function buildPolicySafeEditPrompt(prompt) {
|
|
263493
|
+
const riskyPattern = /\b(watermark|watermarks|logo|logos|copyright|brand mark|remove branding)\b/i;
|
|
263494
|
+
if (!riskyPattern.test(prompt)) {
|
|
263495
|
+
return { prompt, rewritten: false };
|
|
263496
|
+
}
|
|
263497
|
+
return {
|
|
263498
|
+
prompt: "Clean up distracting overlay text or marks naturally while preserving the original scene, style, and layout. Keep the result seamless and high quality.",
|
|
263499
|
+
rewritten: true
|
|
263500
|
+
};
|
|
263501
|
+
}
|
|
263502
|
+
async function saveImageItem(item, filePath, apiKey) {
|
|
263503
|
+
const b64 = await resolveB64(item, apiKey);
|
|
263383
263504
|
if (!b64)
|
|
263384
263505
|
return void 0;
|
|
263385
263506
|
mkdirSync10(dirname19(filePath), { recursive: true });
|
|
@@ -263399,7 +263520,7 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
263399
263520
|
],
|
|
263400
263521
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
263401
263522
|
parameters: generateImageSchema,
|
|
263402
|
-
async execute(_toolCallId, params,
|
|
263523
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
263403
263524
|
const p = params;
|
|
263404
263525
|
const prompt = p.prompt;
|
|
263405
263526
|
const size = p.size ?? "1024x1024";
|
|
@@ -263420,20 +263541,23 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
263420
263541
|
prompt,
|
|
263421
263542
|
n: 1,
|
|
263422
263543
|
size,
|
|
263423
|
-
quality
|
|
263424
|
-
|
|
263544
|
+
quality,
|
|
263545
|
+
response_format: "b64_json",
|
|
263546
|
+
output_format: "png"
|
|
263547
|
+
}),
|
|
263548
|
+
signal
|
|
263425
263549
|
});
|
|
263426
263550
|
if (!res.ok) {
|
|
263427
263551
|
throw new Error(`Image generation failed (${res.status}): ${await res.text()}`);
|
|
263428
263552
|
}
|
|
263429
263553
|
const json = await res.json();
|
|
263430
|
-
const item = json
|
|
263431
|
-
const savedPath = await saveImageItem(item, filePath);
|
|
263554
|
+
const item = pickImageItem(json);
|
|
263555
|
+
const savedPath = await saveImageItem(item, filePath, apiKey);
|
|
263432
263556
|
return {
|
|
263433
263557
|
content: [
|
|
263434
263558
|
{
|
|
263435
263559
|
type: "text",
|
|
263436
|
-
text: savedPath ??
|
|
263560
|
+
text: savedPath ?? `Image generated but could not be saved: no image payload returned; image_model: ${imageModelId}`
|
|
263437
263561
|
}
|
|
263438
263562
|
],
|
|
263439
263563
|
details: {
|
|
@@ -263453,13 +263577,200 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
263453
263577
|
}
|
|
263454
263578
|
};
|
|
263455
263579
|
}
|
|
263580
|
+
var editImageSchema = {
|
|
263581
|
+
type: "object",
|
|
263582
|
+
properties: {
|
|
263583
|
+
image: {
|
|
263584
|
+
type: "string",
|
|
263585
|
+
description: "Path to the source image file to edit (relative to working directory or absolute)."
|
|
263586
|
+
},
|
|
263587
|
+
prompt: {
|
|
263588
|
+
type: "string",
|
|
263589
|
+
description: "Text description of the desired final image. Describe the full result, not just the change."
|
|
263590
|
+
},
|
|
263591
|
+
mask: {
|
|
263592
|
+
type: "string",
|
|
263593
|
+
description: "Optional path to a mask image (PNG with transparent areas indicating where to edit). If omitted, the model decides what to change based on the prompt."
|
|
263594
|
+
},
|
|
263595
|
+
filename: {
|
|
263596
|
+
type: "string",
|
|
263597
|
+
description: "Output filename with extension, e.g. 'edited_cat.png'. Defaults to a timestamp-based name."
|
|
263598
|
+
},
|
|
263599
|
+
size: {
|
|
263600
|
+
type: "string",
|
|
263601
|
+
enum: ["1024x1024", "1024x1536", "1536x1024", "auto"],
|
|
263602
|
+
description: "Output image dimensions. Optional; omit or set auto to let model decide."
|
|
263603
|
+
},
|
|
263604
|
+
quality: {
|
|
263605
|
+
type: "string",
|
|
263606
|
+
enum: ["low", "medium", "high", "auto"],
|
|
263607
|
+
description: "Image quality. Optional; omit or set auto to let model decide."
|
|
263608
|
+
}
|
|
263609
|
+
},
|
|
263610
|
+
required: ["image", "prompt"],
|
|
263611
|
+
additionalProperties: false
|
|
263612
|
+
};
|
|
263613
|
+
function buildMultipartBody(fields, files) {
|
|
263614
|
+
const boundary = `----SandagentBoundary${Date.now()}${Math.random().toString(36).slice(2)}`;
|
|
263615
|
+
const parts = [];
|
|
263616
|
+
for (const { name, value: value2 } of fields) {
|
|
263617
|
+
parts.push(Buffer.from(`--${boundary}\r
|
|
263618
|
+
Content-Disposition: form-data; name="${name}"\r
|
|
263619
|
+
\r
|
|
263620
|
+
${value2}\r
|
|
263621
|
+
`));
|
|
263622
|
+
}
|
|
263623
|
+
for (const { name, filename, buffer, mime } of files) {
|
|
263624
|
+
parts.push(Buffer.from(`--${boundary}\r
|
|
263625
|
+
Content-Disposition: form-data; name="${name}"; filename="${filename}"\r
|
|
263626
|
+
Content-Type: ${mime}\r
|
|
263627
|
+
\r
|
|
263628
|
+
`));
|
|
263629
|
+
parts.push(buffer);
|
|
263630
|
+
parts.push(Buffer.from("\r\n"));
|
|
263631
|
+
}
|
|
263632
|
+
parts.push(Buffer.from(`--${boundary}--\r
|
|
263633
|
+
`));
|
|
263634
|
+
return {
|
|
263635
|
+
body: Buffer.concat(parts),
|
|
263636
|
+
contentType: `multipart/form-data; boundary=${boundary}`
|
|
263637
|
+
};
|
|
263638
|
+
}
|
|
263639
|
+
function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
263640
|
+
return {
|
|
263641
|
+
name: "edit_image",
|
|
263642
|
+
label: "edit image",
|
|
263643
|
+
description: "Edit an existing image based on a text prompt. Optionally use a mask to control which areas to modify. Saves the result to disk and returns the file path.",
|
|
263644
|
+
promptSnippet: "edit_image(image, prompt, mask?, filename?, size?, quality?) - edit an existing image",
|
|
263645
|
+
promptGuidelines: [
|
|
263646
|
+
"Use edit_image when the user wants to modify, retouch, or transform an existing image.",
|
|
263647
|
+
"The prompt should describe the full desired final image, not just the change.",
|
|
263648
|
+
"Provide the source image path. Use a mask image (PNG with transparent areas) to control where edits happen.",
|
|
263649
|
+
"Without a mask, the model decides what to change based on the prompt."
|
|
263650
|
+
],
|
|
263651
|
+
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
263652
|
+
parameters: editImageSchema,
|
|
263653
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
263654
|
+
const { readFileSync: readFileSync24, existsSync: existsSync31 } = await import("node:fs");
|
|
263655
|
+
const { resolve: resolve14, basename: basename12 } = await import("node:path");
|
|
263656
|
+
const p = params;
|
|
263657
|
+
const imagePath = p.image;
|
|
263658
|
+
const prompt = p.prompt;
|
|
263659
|
+
const maskPath = p.mask;
|
|
263660
|
+
const size = p.size;
|
|
263661
|
+
const quality = p.quality;
|
|
263662
|
+
const rawFilename = p.filename;
|
|
263663
|
+
const safePrompt = buildPolicySafeEditPrompt(prompt);
|
|
263664
|
+
const resolvedImage = resolve14(cwd, imagePath);
|
|
263665
|
+
if (!existsSync31(resolvedImage)) {
|
|
263666
|
+
return {
|
|
263667
|
+
content: [
|
|
263668
|
+
{
|
|
263669
|
+
type: "text",
|
|
263670
|
+
text: `Image edit error: source image not found at ${resolvedImage}`
|
|
263671
|
+
}
|
|
263672
|
+
],
|
|
263673
|
+
details: void 0
|
|
263674
|
+
};
|
|
263675
|
+
}
|
|
263676
|
+
const filename = rawFilename ? extname2(rawFilename) ? rawFilename : `${rawFilename}.png` : `edited_${Date.now()}.png`;
|
|
263677
|
+
const filePath = join34(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
|
|
263678
|
+
try {
|
|
263679
|
+
const imageBuffer = readFileSync24(resolvedImage);
|
|
263680
|
+
const fields = [
|
|
263681
|
+
{ name: "model", value: imageModelId },
|
|
263682
|
+
{ name: "prompt", value: safePrompt.prompt },
|
|
263683
|
+
{ name: "n", value: "1" },
|
|
263684
|
+
{ name: "response_format", value: "b64_json" },
|
|
263685
|
+
{ name: "output_format", value: "png" }
|
|
263686
|
+
];
|
|
263687
|
+
if (size && size !== "auto") {
|
|
263688
|
+
fields.push({ name: "size", value: size });
|
|
263689
|
+
}
|
|
263690
|
+
if (quality && quality !== "auto") {
|
|
263691
|
+
fields.push({ name: "quality", value: quality });
|
|
263692
|
+
}
|
|
263693
|
+
const files = [
|
|
263694
|
+
{
|
|
263695
|
+
name: "image",
|
|
263696
|
+
filename: basename12(resolvedImage),
|
|
263697
|
+
buffer: imageBuffer,
|
|
263698
|
+
mime: detectImageMime(resolvedImage)
|
|
263699
|
+
}
|
|
263700
|
+
];
|
|
263701
|
+
if (maskPath) {
|
|
263702
|
+
const resolvedMask = resolve14(cwd, maskPath);
|
|
263703
|
+
if (existsSync31(resolvedMask)) {
|
|
263704
|
+
files.push({
|
|
263705
|
+
name: "mask",
|
|
263706
|
+
filename: basename12(resolvedMask),
|
|
263707
|
+
buffer: readFileSync24(resolvedMask),
|
|
263708
|
+
mime: detectImageMime(resolvedMask)
|
|
263709
|
+
});
|
|
263710
|
+
}
|
|
263711
|
+
}
|
|
263712
|
+
const { body: multipartBody, contentType } = buildMultipartBody(fields, files);
|
|
263713
|
+
const url = `${baseUrl.replace(/\/$/, "")}/v1/images/edits`;
|
|
263714
|
+
const sendRequest = async (body, type) => {
|
|
263715
|
+
const res = await fetch(url, {
|
|
263716
|
+
method: "POST",
|
|
263717
|
+
headers: {
|
|
263718
|
+
"Content-Type": type,
|
|
263719
|
+
Authorization: `Bearer ${apiKey}`
|
|
263720
|
+
},
|
|
263721
|
+
body,
|
|
263722
|
+
signal
|
|
263723
|
+
});
|
|
263724
|
+
if (!res.ok) {
|
|
263725
|
+
throw new Error(`Image edit failed (${res.status}): ${await res.text()}`);
|
|
263726
|
+
}
|
|
263727
|
+
return await res.json();
|
|
263728
|
+
};
|
|
263729
|
+
let json = await sendRequest(multipartBody, contentType);
|
|
263730
|
+
const item = pickImageItem(json);
|
|
263731
|
+
let savedPath = await saveImageItem(item, filePath, apiKey);
|
|
263732
|
+
const firstResponseHasEmptyDataArray = Array.isArray(json.data) && json.data.length === 0;
|
|
263733
|
+
if (!savedPath && safePrompt.rewritten && firstResponseHasEmptyDataArray) {
|
|
263734
|
+
const retryFields = fields.map((f3) => f3.name === "prompt" ? {
|
|
263735
|
+
name: "prompt",
|
|
263736
|
+
value: "Remove only distracting overlay text artifacts naturally and keep all original content unchanged."
|
|
263737
|
+
} : f3);
|
|
263738
|
+
const retryMultipart = buildMultipartBody(retryFields, files);
|
|
263739
|
+
json = await sendRequest(retryMultipart.body, retryMultipart.contentType);
|
|
263740
|
+
const retryItem = pickImageItem(json);
|
|
263741
|
+
savedPath = await saveImageItem(retryItem, filePath, apiKey);
|
|
263742
|
+
}
|
|
263743
|
+
return {
|
|
263744
|
+
content: [
|
|
263745
|
+
{
|
|
263746
|
+
type: "text",
|
|
263747
|
+
text: savedPath ?? `Image edited but could not be saved: no image payload returned; image_model: ${imageModelId}`
|
|
263748
|
+
}
|
|
263749
|
+
],
|
|
263750
|
+
details: {
|
|
263751
|
+
filePath: savedPath,
|
|
263752
|
+
response: json
|
|
263753
|
+
}
|
|
263754
|
+
};
|
|
263755
|
+
} catch (e2) {
|
|
263756
|
+
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
263757
|
+
return {
|
|
263758
|
+
content: [
|
|
263759
|
+
{ type: "text", text: `Image edit error: ${msg}` }
|
|
263760
|
+
],
|
|
263761
|
+
details: void 0
|
|
263762
|
+
};
|
|
263763
|
+
}
|
|
263764
|
+
}
|
|
263765
|
+
};
|
|
263766
|
+
}
|
|
263456
263767
|
|
|
263457
263768
|
// ../../packages/runner-pi/dist/web-tools.js
|
|
263458
263769
|
var braveProvider = {
|
|
263459
263770
|
id: "brave",
|
|
263460
263771
|
label: "Brave Search",
|
|
263461
263772
|
envKeys: ["BRAVE_API_KEY"],
|
|
263462
|
-
async search({ apiKey, query, count, country, freshness }) {
|
|
263773
|
+
async search({ apiKey, query, count, country, freshness, signal }) {
|
|
263463
263774
|
const params = new URLSearchParams({
|
|
263464
263775
|
q: query,
|
|
263465
263776
|
count: String(Math.min(count, 20))
|
|
@@ -263473,7 +263784,8 @@ var braveProvider = {
|
|
|
263473
263784
|
Accept: "application/json",
|
|
263474
263785
|
"Accept-Encoding": "gzip",
|
|
263475
263786
|
"X-Subscription-Token": apiKey
|
|
263476
|
-
}
|
|
263787
|
+
},
|
|
263788
|
+
signal
|
|
263477
263789
|
});
|
|
263478
263790
|
if (!res.ok) {
|
|
263479
263791
|
const body = await res.text().catch(() => "");
|
|
@@ -263501,7 +263813,7 @@ var tavilyProvider = {
|
|
|
263501
263813
|
id: "tavily",
|
|
263502
263814
|
label: "Tavily",
|
|
263503
263815
|
envKeys: ["TAVILY_API_KEY"],
|
|
263504
|
-
async search({ apiKey, query, count }) {
|
|
263816
|
+
async search({ apiKey, query, count, signal }) {
|
|
263505
263817
|
const res = await fetch("https://api.tavily.com/search", {
|
|
263506
263818
|
method: "POST",
|
|
263507
263819
|
headers: { "Content-Type": "application/json" },
|
|
@@ -263510,7 +263822,8 @@ var tavilyProvider = {
|
|
|
263510
263822
|
query,
|
|
263511
263823
|
max_results: Math.min(count, 10),
|
|
263512
263824
|
include_answer: false
|
|
263513
|
-
})
|
|
263825
|
+
}),
|
|
263826
|
+
signal
|
|
263514
263827
|
});
|
|
263515
263828
|
if (!res.ok) {
|
|
263516
263829
|
const body = await res.text().catch(() => "");
|
|
@@ -263563,9 +263876,12 @@ var BROWSER_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/53
|
|
|
263563
263876
|
function htmlToText(html2) {
|
|
263564
263877
|
return html2.replace(/<(script|style|noscript)[^>]*>[\s\S]*?<\/\1>/gi, "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|h[1-6]|li|tr)>/gi, "\n").replace(/<(p|div|h[1-6]|li|tr)[^>]*>/gi, "\n").replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
263565
263878
|
}
|
|
263566
|
-
async function fetchPageContent(url) {
|
|
263879
|
+
async function fetchPageContent(url, externalSignal) {
|
|
263567
263880
|
const controller = new AbortController();
|
|
263568
263881
|
const timeout = setTimeout(() => controller.abort(), 15e3);
|
|
263882
|
+
externalSignal?.addEventListener("abort", () => controller.abort(), {
|
|
263883
|
+
once: true
|
|
263884
|
+
});
|
|
263569
263885
|
try {
|
|
263570
263886
|
const res = await fetch(url, {
|
|
263571
263887
|
headers: {
|
|
@@ -263662,7 +263978,7 @@ function buildWebSearchTool(env2) {
|
|
|
263662
263978
|
],
|
|
263663
263979
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
263664
263980
|
parameters: webSearchSchema,
|
|
263665
|
-
async execute(_toolCallId, params,
|
|
263981
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
263666
263982
|
const p = params;
|
|
263667
263983
|
const query = p.query;
|
|
263668
263984
|
const count = p.count ?? 5;
|
|
@@ -263677,11 +263993,12 @@ function buildWebSearchTool(env2) {
|
|
|
263677
263993
|
query,
|
|
263678
263994
|
count,
|
|
263679
263995
|
country,
|
|
263680
|
-
freshness
|
|
263996
|
+
freshness,
|
|
263997
|
+
signal
|
|
263681
263998
|
});
|
|
263682
263999
|
if (shouldFetchContent) {
|
|
263683
264000
|
for (const r2 of results) {
|
|
263684
|
-
r2.content = await fetchPageContent(r2.link);
|
|
264001
|
+
r2.content = await fetchPageContent(r2.link, signal);
|
|
263685
264002
|
}
|
|
263686
264003
|
}
|
|
263687
264004
|
return {
|
|
@@ -263727,11 +264044,11 @@ function buildWebFetchTool() {
|
|
|
263727
264044
|
],
|
|
263728
264045
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
263729
264046
|
parameters: webFetchSchema,
|
|
263730
|
-
async execute(_toolCallId, params,
|
|
264047
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
263731
264048
|
const p = params;
|
|
263732
264049
|
const url = p.url;
|
|
263733
264050
|
try {
|
|
263734
|
-
const content = await fetchPageContent(url);
|
|
264051
|
+
const content = await fetchPageContent(url, signal);
|
|
263735
264052
|
return {
|
|
263736
264053
|
content: [{ type: "text", text: content }],
|
|
263737
264054
|
details: void 0
|
|
@@ -264024,7 +264341,7 @@ function createPiRunner(options2 = {}) {
|
|
|
264024
264341
|
const customTools = options2.env && Object.keys(options2.env).length > 0 ? buildSecretAwareTools(cwd, options2.env) : [];
|
|
264025
264342
|
if (imageModelName) {
|
|
264026
264343
|
const apiKey = await modelRegistry2.authStorage.getApiKey(provider) ?? "";
|
|
264027
|
-
customTools.push(buildImageGenerateTool(cwd, imageModelName, model.baseUrl, apiKey));
|
|
264344
|
+
customTools.push(buildImageGenerateTool(cwd, imageModelName, model.baseUrl, apiKey), buildImageEditTool(cwd, imageModelName, model.baseUrl, apiKey));
|
|
264028
264345
|
}
|
|
264029
264346
|
const { session } = await createAgentSession({
|
|
264030
264347
|
cwd,
|
|
@@ -264195,7 +264512,7 @@ function createPiRunner(options2 = {}) {
|
|
|
264195
264512
|
if (options2.env && Object.keys(options2.env).length > 0) {
|
|
264196
264513
|
output = redactSecrets(output, options2.env);
|
|
264197
264514
|
}
|
|
264198
|
-
if (event.toolName === "generate_image" && event.result !== null && typeof event.result === "object") {
|
|
264515
|
+
if ((event.toolName === "generate_image" || event.toolName === "edit_image") && event.result !== null && typeof event.result === "object") {
|
|
264199
264516
|
const details = event.result.details;
|
|
264200
264517
|
const u = details?.response?.usage;
|
|
264201
264518
|
if (u) {
|
|
@@ -264426,7 +264743,8 @@ function codingRunStream(req, env2) {
|
|
|
264426
264743
|
cwd: req.cwd ?? process.env.BUNNY_AGENT_ROOT ?? "/workspace",
|
|
264427
264744
|
yolo: req.yolo,
|
|
264428
264745
|
env: env2,
|
|
264429
|
-
abortController
|
|
264746
|
+
abortController,
|
|
264747
|
+
autoInject: false
|
|
264430
264748
|
});
|
|
264431
264749
|
for await (const chunk of stream2) {
|
|
264432
264750
|
controller.enqueue(encoder.encode(chunk));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coding.d.ts","sourceRoot":"","sources":["../../src/routes/coding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAGvC,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAKD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,sCAAsC;AACtC,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"coding.d.ts","sourceRoot":"","sources":["../../src/routes/coding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAGvC,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAKD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD,sCAAsC;AACtC,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoDf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,QAAQ,CA6DV"}
|