Install
openclaw skills install @likely7/doubaoimagesGenerate images with Doubao web chat, extract the final generated image URL from the page, save the image locally, and return the saved local path. Use when the user wants a low-cost browser-based image generation workflow instead of paid image APIs, especially for portraits, concept images, and local saving.
openclaw skills install @likely7/doubaoimagesUse this skill when the user wants to:
Collect or infer:
prompt: image prompt for 豆包output_path: local save pathIf the user does not specify an output path, default to a timestamped file name in:
C:\Users\Administrator\.openclaw\workspace\tmp\Use this naming pattern:
doubao-YYYYMMDD-HHMMSS.pngExample:
C:\Users\Administrator\.openclaw\workspace\tmp\doubao-20260318-131500.pngOpen:
https://www.doubao.com/chat/Assume the user may already be logged in. Do not force re-login unless the page clearly requires it.
Preferred path:
If normal browser click/type fails on the textbox, use browser evaluate fallback.
Use this pattern when needed:
() => {
const ta = document.querySelector('textarea');
if (!ta) return { ok: false, reason: 'no textarea' };
const text = 'PROMPT_HERE';
const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
setter.call(ta, text);
ta.dispatchEvent(new Event('input', { bubbles: true }));
ta.dispatchEvent(new Event('change', { bubbles: true }));
return { ok: true, valueLength: ta.value.length };
}
If Enter does not submit, click the likely send button near the lower-right side of the input area.
Do not assume the first visible image URL is the original file. Visible Doubao images often use display URLs containing clues like:
downsizewatermarkThose are usually preview assets, not the best download source.
Use this priority order:
After generation completes:
下载If preview opens but no explicit download button is found, inspect images again while the large preview is open. Prefer the image candidate with the largest natural dimensions.
Use this pattern:
() => {
return [...document.images]
.map((img, i) => ({
i,
src: img.src,
width: img.naturalWidth,
height: img.naturalHeight,
alt: img.alt || ''
}))
.filter(x => x.width > 100 && x.height > 100)
.filter(x => !x.src.startsWith('data:image/svg+xml'))
.sort((a, b) => (b.width * b.height) - (a.width * a.height));
}
If no preview/download path works, inspect normal page images and rank them. Use this pattern:
() => {
return [...document.images]
.map((img, i) => ({
i,
src: img.src,
width: img.naturalWidth,
height: img.naturalHeight,
alt: img.alt || '',
score: (img.naturalWidth * img.naturalHeight)
}))
.filter(x => x.width > 100 && x.height > 100)
.filter(x => !x.src.startsWith('data:image/svg+xml'))
.sort((a, b) => b.score - a.score);
}
Pick the best result by this order:
downsize / watermarkWhen comparing URLs, prefer the one that:
downsizeimage_pre or original image-generation asset URLs over tiny chat thumbnailswatermark variants when they are still the highest-quality accessible previewDownload the chosen URL directly to a local file.
If the user did not provide output_path, generate one with a timestamp first.
Use this pattern:
@'
from datetime import datetime
import pathlib
base = pathlib.Path(r'C:\Users\Administrator\.openclaw\workspace\tmp')
base.mkdir(parents=True, exist_ok=True)
out = base / f"doubao-{datetime.now().strftime('%Y%m%d-%H%M%S')}.png"
print(out)
'@ | python -
Then download to that path:
@'
import urllib.request
url = 'IMAGE_URL_HERE'
out = r'OUTPUT_PATH_HERE'
urllib.request.urlretrieve(url, out)
print(out)
'@ | python -
After saving, confirm the file exists and return:
To reduce token waste:
Ask the user to log in on the opened page, then continue.
Refresh once and retry. If still missing, inspect for iframe or layout change.
Try this sequence:
下载 button or download-style controldownsize/watermark, use the largest fallback URLWait once more, inspect DOM again, then fall back to screenshot-based capture only if absolutely necessary.