feat: add jimeng (即梦AI) CLI support (#57)

Add two CLI commands for Jimeng (即梦AI) — ByteDance's AI image generation platform:

- generate: Text-to-image generation with model selection and configurable wait time
- history: View recent generation history with prompt, model, status, and image URLs

Both commands use browser automation with cookie-based authentication on jimeng.jianying.com.
This commit is contained in:
stometaverse authored and GitHub committed 2026-03-18 20:23:45 +08:00
1 parent e76de39f42
commit a06cdbf0ac
2 files changed
+131

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
site: jimeng
name: generate
description: 即梦AI 文生图 — 输入 prompt 生成图片
domain: jimeng.jianying.com
strategy: cookie
browser: true
args:
prompt:
type: string
required: true
description: "图片描述 prompt"
model:
type: string
default: "high_aes_general_v50"
description: "模型: high_aes_general_v50 (5.0 Lite), high_aes_general_v42 (4.6), high_aes_general_v40 (4.0)"
wait:
type: int
default: 40
description: "等待生成完成的秒数"
columns: [status, prompt, image_count, image_urls]
pipeline:
- navigate: https://jimeng.jianying.com/ai-tool/generate?type=image&workspace=0
- wait: 3
- evaluate: |
(async () => {
const prompt = ${{ args.prompt | json }};
const waitSec = ${{ args.wait }};
// Step 1: Count existing images before generation
const beforeImgs = document.querySelectorAll('img[src*="dreamina-sign"], img[src*="tb4s082cfz"]').length;
// Step 2: Clear and set prompt
const editors = document.querySelectorAll('[contenteditable="true"]');
const editor = editors[0];
if (!editor) return [{ status: 'failed', prompt: prompt, image_count: 0, image_urls: 'Editor not found' }];
editor.focus();
await new Promise(r => setTimeout(r, 200));
document.execCommand('selectAll');
await new Promise(r => setTimeout(r, 100));
document.execCommand('delete');
await new Promise(r => setTimeout(r, 200));
document.execCommand('insertText', false, prompt);
await new Promise(r => setTimeout(r, 500));
// Step 3: Click generate
const btn = document.querySelector('.lv-btn.lv-btn-primary[class*="circle"]');
if (!btn) return [{ status: 'failed', prompt: prompt, image_count: 0, image_urls: 'Generate button not found' }];
btn.click();
// Step 4: Wait for new images to appear
let newImgs = [];
for (let i = 0; i < waitSec; i++) {
await new Promise(r => setTimeout(r, 1000));
const allImgs = document.querySelectorAll('img[src*="dreamina-sign"], img[src*="tb4s082cfz"]');
if (allImgs.length > beforeImgs) {
// New images appeared — generation complete
newImgs = Array.from(allImgs).slice(0, allImgs.length - beforeImgs);
break;
}
}
if (newImgs.length === 0) {
return [{ status: 'timeout', prompt: prompt, image_count: 0, image_urls: 'Generation may still be in progress' }];
}
// Step 5: Extract image URLs (use thumbnail URLs which are accessible)
const urls = newImgs.map(img => img.src);
return [{
status: 'success',
prompt: prompt.substring(0, 80),
image_count: urls.length,
image_urls: urls.join('\n')
}];
})()
- map:
status: ${{ item.status }}
prompt: ${{ item.prompt }}
image_count: ${{ item.image_count }}
image_urls: ${{ item.image_urls }}
+47
View File
@@ -0,0 +1,47 @@
site: jimeng
name: history
description: 即梦AI 查看最近生成的作品
domain: jimeng.jianying.com
strategy: cookie
browser: true
args:
limit:
type: int
default: 5
columns: [prompt, model, status, image_url, created_at]
pipeline:
- navigate: https://jimeng.jianying.com/ai-tool/generate?type=image&workspace=0
- wait: 3
- evaluate: |
(async () => {
const limit = ${{ args.limit }};
const res = await fetch('/mweb/v1/get_history?aid=513695&device_platform=web&region=cn&da_version=3.3.11&web_version=7.5.0&aigc_features=app_lip_sync', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ cursor: '', count: limit, need_page_item: true, need_aigc_data: true, aigc_mode_list: ['workbench'] })
});
const data = await res.json();
const items = data?.data?.history_list || [];
return items.slice(0, limit).map(item => {
const params = item.aigc_image_params?.text2image_params || {};
const images = item.image?.large_images || [];
return {
prompt: params.prompt || item.common_attr?.title || 'N/A',
model: params.model_config?.model_name || 'unknown',
status: item.common_attr?.status === 102 ? 'completed' : 'pending',
image_url: images[0]?.image_url || '',
created_at: new Date((item.common_attr?.create_time || 0) * 1000).toLocaleString('zh-CN'),
};
});
})()
- map:
prompt: ${{ item.prompt }}
model: ${{ item.model }}
status: ${{ item.status }}
image_url: ${{ item.image_url }}
created_at: ${{ item.created_at }}
- limit: ${{ args.limit }}