Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion acp_adapter/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"delegate_task": "execute",
"vision_analyze": "read",
"image_generate": "execute",
"image_edit": "execute",
"text_to_speech": "execute",
# Thinking / meta
"_thinking": "think",
Expand All @@ -65,7 +66,7 @@
"skill_view", "skills_list", "skill_manage", "web_search", "web_extract",
"browser_navigate", "browser_click", "browser_type", "browser_press", "browser_scroll",
"browser_back", "browser_snapshot", "browser_console", "browser_get_images", "browser_vision",
"vision_analyze", "image_generate", "text_to_speech",
"vision_analyze", "image_generate", "image_edit", "text_to_speech",
# Schedulers / platform integrations
"cronjob", "send_message", "clarify", "discord", "discord_admin",
"ha_list_entities", "ha_get_state", "ha_list_services", "ha_call_service",
Expand Down Expand Up @@ -173,6 +174,9 @@ def build_tool_title(tool_name: str, args: Dict[str, Any]) -> str:
if tool_name == "image_generate":
prompt = str(args.get("prompt") or args.get("description") or "").strip()
return f"generate image: {prompt[:50]}" if prompt else "generate image"
if tool_name == "image_edit":
prompt = str(args.get("prompt") or args.get("instruction") or "").strip()
return f"edit image: {prompt[:50]}" if prompt else "edit image"
if tool_name == "cronjob":
action = str(args.get("action") or "manage").strip() or "manage"
job_id = str(args.get("job_id") or args.get("id") or "").strip()
Expand Down Expand Up @@ -894,6 +898,7 @@ def _build_polished_completion_content(
"browser_get_images": lambda: _format_browser_result(tool_name, result, function_args),
"vision_analyze": lambda: _format_media_or_cron_result(tool_name, result),
"image_generate": lambda: _format_media_or_cron_result(tool_name, result),
"image_edit": lambda: _format_media_or_cron_result(tool_name, result),
"cronjob": lambda: _format_media_or_cron_result(tool_name, result),
}.get(tool_name)
if formatter is None and tool_name in _POLISHED_TOOLS:
Expand Down
4 changes: 3 additions & 1 deletion agent/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def build_tool_preview(tool_name: str, args: dict, max_len: int | None = None) -
"read_file": "path", "write_file": "path", "patch": "path",
"search_files": "pattern", "browser_navigate": "url",
"browser_click": "ref", "browser_type": "text",
"image_generate": "prompt", "text_to_speech": "text",
"image_generate": "prompt", "image_edit": "prompt", "text_to_speech": "text",
"vision_analyze": "question", "mixture_of_agents": "user_prompt",
"skill_view": "name", "skills_list": "category",
"cronjob": "action",
Expand Down Expand Up @@ -999,6 +999,8 @@ def _wrap(line: str) -> str:
return _wrap(f"┊ 📚 skill {_trunc(args.get('name', ''), 30)} {dur}")
if tool_name == "image_generate":
return _wrap(f"┊ 🎨 create {_trunc(args.get('prompt', ''), 35)} {dur}")
if tool_name == "image_edit":
return _wrap(f"┊ 🖌️ edit {_trunc(args.get('prompt', ''), 35)} {dur}")
if tool_name == "text_to_speech":
return _wrap(f"┊ 🔊 speak {_trunc(args.get('text', ''), 30)} {dur}")
if tool_name == "vision_analyze":
Expand Down
32 changes: 32 additions & 0 deletions agent/image_gen_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,38 @@ def generate(
should ignore unknown keys.
"""

def supports_edit(self) -> bool:
"""Return True when this backend supports reference-image editing.

Providers that support image-to-image editing via :meth:`edit` should
override this to return ``True``. The default returns ``False`` so
existing providers stay source-compatible.
"""
return False

def edit(
self,
prompt: str,
image: str,
aspect_ratio: str = DEFAULT_ASPECT_RATIO,
**kwargs: Any,
) -> Dict[str, Any]:
"""Edit an existing image using a text instruction.

``image`` is an HTTP(S) URL, data URL, or absolute local file path.
Providers that support image-to-image should override this method.
The default returns a uniform unsupported error so callers don't need
to probe :meth:`supports_edit` first.
"""
aspect = resolve_aspect_ratio(aspect_ratio)
return error_response(
error=f"Image editing is not supported by provider '{self.name}'",
error_type="unsupported_operation",
provider=self.name,
prompt=prompt or "",
aspect_ratio=aspect,
)


# ---------------------------------------------------------------------------
# Helpers
Expand Down
1 change: 1 addition & 0 deletions agent/prompt_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,7 @@ def build_nous_subscription_prompt(valid_tool_names: "set[str] | None" = None) -
"browser_get_images",
"browser_vision",
"image_generate",
"image_edit",
"text_to_speech",
"terminal",
"process",
Expand Down
1 change: 1 addition & 0 deletions agent/transports/hermes_tools_mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"browser_vision",
"vision_analyze",
"image_generate",
"image_edit",
"skill_view",
"skills_list",
"text_to_speech",
Expand Down
2 changes: 1 addition & 1 deletion hermes_cli/tools_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
("code_execution", "⚡ Code Execution", "execute_code"),
("vision", "👁️ Vision / Image Analysis", "vision_analyze"),
("video", "🎬 Video Analysis", "video_analyze (requires video-capable model)"),
("image_gen", "🎨 Image Generation", "image_generate"),
("image_gen", "🎨 Image Generation / Editing", "image_generate / image_edit"),
("video_gen", "🎬 Video Generation", "video_generate (text-to-video + image-to-video)"),
("x_search", "🐦 X (Twitter) Search", "x_search (requires xAI OAuth or XAI_API_KEY)"),
("moa", "🧠 Mixture of Agents", "mixture_of_agents"),
Expand Down
2 changes: 1 addition & 1 deletion model_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def _run_in_worker():
"terminal_tools": ["terminal"],
"vision_tools": ["vision_analyze"],
"moa_tools": ["mixture_of_agents"],
"image_tools": ["image_generate"],
"image_tools": ["image_generate", "image_edit"],
"skills_tools": ["skills_list", "skill_view", "skill_manage"],
"browser_tools": [
"browser_navigate", "browser_snapshot", "browser_click",
Expand Down
Loading
Loading