Loading...
Loading...
Compare original and translation side by side
https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.pnghttps://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.pngFAL_KEY=your_fal_api_key # Get from https://fal.ai/dashboard/keys
OPENCLAW_GATEWAY_TOKEN=your_token # From: openclaw doctor --generate-gateway-tokenFAL_KEY=your_fal_api_key # 从 https://fal.ai/dashboard/keys 获取
OPENCLAW_GATEWAY_TOKEN=your_token # 通过以下命令生成:openclaw doctor --generate-gateway-tokenmirrordirect#general@usernamemirrordirect#general@usernamemake a pic of this person, but [user's context]. the person is taking a mirror selfiemake a pic of this person, but wearing a santa hat. the person is taking a mirror selfiemake a pic of this person, but [user's context]. the person is taking a mirror selfiemake a pic of this person, but wearing a santa hat. the person is taking a mirror selfiea close-up selfie taken by herself at [user's context], direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visiblea close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visiblea close-up selfie taken by herself at [user's context], direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visiblea close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible| Keywords in Request | Auto-Select Mode |
|---|---|
| outfit, wearing, clothes, dress, suit, fashion | |
| cafe, restaurant, beach, park, city, location | |
| close-up, portrait, face, eyes, smile | |
| full-body, mirror, reflection | |
| 请求中的关键词 | 自动选择模式 |
|---|---|
| outfit, wearing, clothes, dress, suit, fashion | |
| cafe, restaurant, beach, park, city, location | |
| close-up, portrait, face, eyes, smile | |
| full-body, mirror, reflection | |
REFERENCE_IMAGE="https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png"REFERENCE_IMAGE="https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png"
**Response Format:**
```json
{
"images": [
{
"url": "https://v3b.fal.media/files/...",
"content_type": "image/jpeg",
"width": 1024,
"height": 1024
}
],
"revised_prompt": "Enhanced prompt text..."
}
**响应格式:**
```json
{
"images": [
{
"url": "https://v3b.fal.media/files/...",
"content_type": "image/jpeg",
"width": 1024,
"height": 1024
}
],
"revised_prompt": "Enhanced prompt text..."
}openclaw message send \
--action send \
--channel "<TARGET_CHANNEL>" \
--message "<CAPTION_TEXT>" \
--media "<IMAGE_URL>"curl -X POST "http://localhost:18789/message" \
-H "Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "send",
"channel": "<TARGET_CHANNEL>",
"message": "<CAPTION_TEXT>",
"media": "<IMAGE_URL>"
}'openclaw message send \
--action send \
--channel "<TARGET_CHANNEL>" \
--message "<CAPTION_TEXT>" \
--media "<IMAGE_URL>"curl -X POST "http://localhost:18789/message" \
-H "Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "send",
"channel": "<TARGET_CHANNEL>",
"message": "<CAPTION_TEXT>",
"media": "<IMAGE_URL>"
}'#!/bin/bash#!/bin/bashundefinedundefinedimport { fal } from "@fal-ai/client";
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
const REFERENCE_IMAGE = "https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png";
interface GrokImagineResult {
images: Array<{
url: string;
content_type: string;
width: number;
height: number;
}>;
revised_prompt?: string;
}
type SelfieMode = "mirror" | "direct" | "auto";
function detectMode(userContext: string): "mirror" | "direct" {
const mirrorKeywords = /outfit|wearing|clothes|dress|suit|fashion|full-body|mirror/i;
const directKeywords = /cafe|restaurant|beach|park|city|close-up|portrait|face|eyes|smile/i;
if (directKeywords.test(userContext)) return "direct";
if (mirrorKeywords.test(userContext)) return "mirror";
return "mirror"; // default
}
function buildPrompt(userContext: string, mode: "mirror" | "direct"): string {
if (mode === "direct") {
return `a close-up selfie taken by herself at ${userContext}, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible`;
}
return `make a pic of this person, but ${userContext}. the person is taking a mirror selfie`;
}
async function editAndSend(
userContext: string,
channel: string,
mode: SelfieMode = "auto",
caption?: string
): Promise<string> {
// Configure fal.ai client
fal.config({
credentials: process.env.FAL_KEY!
});
// Determine mode
const actualMode = mode === "auto" ? detectMode(userContext) : mode;
console.log(`Mode: ${actualMode}`);
// Construct the prompt
const editPrompt = buildPrompt(userContext, actualMode);
// Edit reference image with Grok Imagine
console.log(`Editing image: "${editPrompt}"`);
const result = await fal.subscribe("xai/grok-imagine-image/edit", {
input: {
image_url: REFERENCE_IMAGE,
prompt: editPrompt,
num_images: 1,
output_format: "jpeg"
}
}) as { data: GrokImagineResult };
const imageUrl = result.data.images[0].url;
console.log(`Edited image URL: ${imageUrl}`);
// Send via OpenClaw
const messageCaption = caption || `Edited with Grok Imagine`;
await execAsync(
`openclaw message send --action send --channel "${channel}" --message "${messageCaption}" --media "${imageUrl}"`
);
console.log(`Sent to ${channel}`);
return imageUrl;
}
// Usage Examples
// Mirror mode (auto-detected from "wearing")
editAndSend(
"wearing a cyberpunk outfit with neon lights",
"#art-gallery",
"auto",
"Check out this AI-edited art!"
);
// → Mode: mirror
// → Prompt: "make a pic of this person, but wearing a cyberpunk outfit with neon lights. the person is taking a mirror selfie"
// Direct mode (auto-detected from "cafe")
editAndSend(
"a cozy cafe with warm lighting",
"#photography",
"auto"
);
// → Mode: direct
// → Prompt: "a close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact..."
// Explicit mode override
editAndSend("casual street style", "#fashion", "direct");import { fal } from "@fal-ai/client";
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
const REFERENCE_IMAGE = "https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png";
interface GrokImagineResult {
images: Array<{
url: string;
content_type: string;
width: number;
height: number;
}>;
revised_prompt?: string;
}
type SelfieMode = "mirror" | "direct" | "auto";
function detectMode(userContext: string): "mirror" | "direct" {
const mirrorKeywords = /outfit|wearing|clothes|dress|suit|fashion|full-body|mirror/i;
const directKeywords = /cafe|restaurant|beach|park|city|close-up|portrait|face|eyes|smile/i;
if (directKeywords.test(userContext)) return "direct";
if (mirrorKeywords.test(userContext)) return "mirror";
return "mirror"; // 默认模式
}
function buildPrompt(userContext: string, mode: "mirror" | "direct"): string {
if (mode === "direct") {
return `a close-up selfie taken by herself at ${userContext}, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible`;
}
return `make a pic of this person, but ${userContext}. the person is taking a mirror selfie`;
}
async function editAndSend(
userContext: string,
channel: string,
mode: SelfieMode = "auto",
caption?: string
): Promise<string> {
// 配置fal.ai客户端
fal.config({
credentials: process.env.FAL_KEY!
});
// 确定模式
const actualMode = mode === "auto" ? detectMode(userContext) : mode;
console.log(`Mode: ${actualMode}`);
// 构建提示词
const editPrompt = buildPrompt(userContext, actualMode);
// 使用Grok Imagine编辑参考图片
console.log(`Editing image: "${editPrompt}"`);
const result = await fal.subscribe("xai/grok-imagine-image/edit", {
input: {
image_url: REFERENCE_IMAGE,
prompt: editPrompt,
num_images: 1,
output_format: "jpeg"
}
}) as { data: GrokImagineResult };
const imageUrl = result.data.images[0].url;
console.log(`Edited image URL: ${imageUrl}`);
// 通过OpenClaw发送图片
const messageCaption = caption || `Edited with Grok Imagine`;
await execAsync(
`openclaw message send --action send --channel "${channel}" --message "${messageCaption}" --media "${imageUrl}"`
);
console.log(`Sent to ${channel}`);
return imageUrl;
}
// 使用示例
// 镜像模式(通过关键词"wearing"自动检测)
editAndSend(
"wearing a cyberpunk outfit with neon lights",
"#art-gallery",
"auto",
"Check out this AI-edited art!"
);
// → Mode: mirror
// → Prompt: "make a pic of this person, but wearing a cyberpunk outfit with neon lights. the person is taking a mirror selfie"
// 直面模式(通过关键词"cafe"自动检测)
editAndSend(
"a cozy cafe with warm lighting",
"#photography",
"auto"
);
// → Mode: direct
// → Prompt: "a close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact..."
// 手动指定模式
editAndSend("casual street style", "#fashion", "direct");| Platform | Channel Format | Example |
|---|---|---|
| Discord | | |
| Telegram | | |
| Phone number (JID format) | | |
| Slack | | |
| Signal | Phone number | |
| MS Teams | Channel reference | (varies) |
| 平台 | 渠道格式 | 示例 |
|---|---|---|
| Discord | | |
| Telegram | | |
| 电话号码(JID格式) | | |
| Slack | | |
| Signal | 电话号码 | |
| MS Teams | 渠道引用 | (格式不固定) |
| Parameter | Type | Default | Description |
|---|---|---|---|
| string | required | URL of image to edit (fixed in this skill) |
| string | required | Edit instruction |
| 1-4 | 1 | Number of images to generate |
| enum | "jpeg" | jpeg, png, webp |
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| string | 必填 | 待编辑图片的URL(本技能中为固定值) |
| string | 必填 | 编辑指令 |
| 1-4 | 1 | 生成的图片数量 |
| enum | "jpeg" | 输出格式:jpeg, png, webp |
npm install @fal-ai/clientnpm install @fal-ai/clientnpm install -g openclawnpm install -g openclawopenclaw config set gateway.mode=local
openclaw doctor --generate-gateway-tokenopenclaw config set gateway.mode=local
openclaw doctor --generate-gateway-tokenopenclaw gateway startopenclaw gateway start