Merge pull request #922 from zanllp/docs/improve-skill-for-agents

docs: improve skill docs for better agent integration
docs/reorganize-skill-references
zanllp 2026-02-18 21:26:18 +08:00 committed by GitHub
commit c3defd180a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 419 additions and 269 deletions

View File

@ -56,6 +56,7 @@ If you would like to support more software, please refer to: [parsers](https://g
- You can run it independently using Python.
- The desktop app version is also available.
- Supports multiple popular AI software.
- **NEW**: Use with AI agents (Claude Code, Cursor, OpenClaw, etc.) via Agent Skills.
### 🎵 TikTok-Style View
@ -151,6 +152,31 @@ If you need to compile it yourself, please refer to https://github.com/zanllp/sd
Use iframe to access IIB and use it as a file browser for your application. Refer to https://github.com/zanllp/sd-webui-infinite-image-browsing/blob/main/vue/usage.md
## With AI Agents (Claude Code, Cursor, OpenClaw, etc.)
IIB can be used as an [Agent Skill](https://agentskills.io), allowing AI agents to search, browse, tag, and organize your images through natural language.
### Installation
```bash
npx skills add https://github.com/zanllp/infinite-image-browsing --skill iib
```
### Usage
1. Start IIB service first:
```bash
python app.py --port 7866
```
2. Then ask your AI agent to help with image tasks:
- "Find all images with 'sunset' in the prompt"
- "Tag these images as favorites"
- "Organize my Downloads folder by theme"
- "Show me the generation parameters of this image"
The agent will use IIB's API to perform these operations. See [skills/iib/SKILL.md](skills/iib/SKILL.md) for the full API documentation.
# Preview

View File

@ -1,268 +0,0 @@
---
name: IIB API
description: Access IIB (Infinite Image Browsing) APIs for image searching, browsing, tagging, and AI-powered organization.
---
# IIB (Infinite Image Browsing) API Skill
IIB is a powerful image/video browsing, searching, and management tool with support for parsing metadata from multiple AI generation tools.
## Starting the Service
### Method 1: Standalone Mode (Recommended)
```bash
# Basic startup
python app.py --port 8000 --host 127.0.0.1
# With extra scan paths
python app.py --port 8000 --extra_paths /path/to/images /another/path
# Update index on startup
python app.py --port 8000 --extra_paths /path/to/images --update_image_index
# Enable CORS for external access
python app.py --port 8000 --allow_cors
# Full example
python app.py --port 8000 --host 0.0.0.0 --allow_cors --extra_paths /my/images --update_image_index
```
### Method 2: As SD WebUI Extension
Place the project in `extensions/sd-webui-infinite-image-browsing` directory and start with SD WebUI.
API Base URL: `http://localhost:7860/infinite_image_browsing`
### Method 3: Python Code Integration
```python
from app import launch_app, AppUtils
from fastapi import FastAPI
# Option A: Direct launch
launch_app(port=8000, extra_paths=["/my/images"], allow_cors=True)
# Option B: Mount to existing FastAPI app
app = FastAPI()
app_utils = AppUtils(extra_paths=["/my/images"], allow_cors=True)
app_utils.wrap_app(app)
# Option C: Async launch for Jupyter Notebook
import asyncio
await async_launch_app(port=8000, extra_paths=["/my/images"])
```
### Environment Variables
```bash
# Authentication key (optional, enables API authentication)
export IIB_SECRET_KEY="your_secret_key"
# AI features configuration (required for clustering, smart organization)
export OPENAI_API_KEY="sk-xxx"
export OPENAI_BASE_URL="https://api.openai.com/v1" # or compatible endpoint
export AI_MODEL="gpt-4o-mini"
export EMBEDDING_MODEL="text-embedding-3-small"
# Access control
export IIB_ACCESS_CONTROL_ALLOWED_PATHS="/path1,/path2"
export IIB_ACCESS_CONTROL_PERMISSION="read-write" # read-only | read-write | write-only
```
---
## Core Feature: Image Search
IIB provides multiple image search methods - this is its core capability.
> **Note:** The examples below use Python for illustration, but you can use any language (Node.js, Go, Rust, etc.) that supports HTTP requests. The API is language-agnostic REST.
### 1. Substring Search (Fuzzy Search)
Search images by text in file path or generation parameters.
```python
import requests
BASE_URL = "http://localhost:8000/infinite_image_browsing"
# Search images containing "landscape"
resp = requests.post(f"{BASE_URL}/db/search_by_substr", json={
"surstr": "landscape", # Search keyword
"cursor": "", # Pagination cursor, empty for first page
"regexp": "", # Regular expression (optional)
"size": 100, # Results per page
"folder_paths": [], # Limit to specific directories (optional)
"media_type": "image" # "all" | "image" | "video"
})
result = resp.json()
for file in result["files"]:
print(file["fullpath"], file["size"])
# Pagination
if result["cursor"]["has_next"]:
next_resp = requests.post(f"{BASE_URL}/db/search_by_substr", json={
"surstr": "landscape",
"cursor": result["cursor"]["next"],
"regexp": "",
"size": 100
})
```
### 2. Regular Expression Search
Use regex for precise pattern matching.
```python
# Search images with filenames starting with numbers
resp = requests.post(f"{BASE_URL}/db/search_by_substr", json={
"surstr": "",
"cursor": "",
"regexp": r"^\d+.*\.png$", # Regex pattern
"size": 100
})
# Search images with specific prompt format
resp = requests.post(f"{BASE_URL}/db/search_by_substr", json={
"surstr": "",
"cursor": "",
"regexp": r"masterpiece.*1girl.*blue eyes",
"size": 100
})
```
### 3. Tag-based Search
Search by custom tags with AND/OR/NOT logic.
```python
# First get all tags
tags_resp = requests.get(f"{BASE_URL}/db/basic_info")
all_tags = tags_resp.json()["tags"]
# tags format: [{"id": 1, "name": "favorites", "type": "custom"}, ...]
# Search: (tag_id=1 AND tag_id=2) OR tag_id=3, excluding tag_id=4
resp = requests.post(f"{BASE_URL}/db/match_images_by_tags", json={
"and_tags": [1, 2], # Must have all these tags
"or_tags": [3], # Have any of these
"not_tags": [4], # Exclude these tags
"cursor": "",
"size": 100,
"folder_paths": [], # Limit to directories (optional)
"random_sort": False # Random order
})
```
### 4. Directory Browsing
List files and subdirectories in a folder.
```python
# List directory contents
resp = requests.get(f"{BASE_URL}/files", params={
"folder_path": "/path/to/images"
})
files = resp.json()["files"]
for f in files:
if f["type"] == "dir":
print(f"[DIR] {f['name']}")
else:
print(f"[FILE] {f['name']} - {f['size']}")
```
### 5. Random Images
Get random images from the database.
```python
resp = requests.get(f"{BASE_URL}/db/random_images")
random_images = resp.json() # Returns 128 random images
```
### 6. AI Semantic Clustering
Cluster images by semantic similarity of generation parameters.
```python
# Start clustering job
start_resp = requests.post(f"{BASE_URL}/db/cluster_iib_output_job_start", json={
"folder_paths": ["/path/to/images"],
"threshold": 0.85, # Similarity threshold
"min_cluster_size": 3, # Minimum cluster size
"lang": "en", # Title language
"recursive": True # Include subdirectories
})
job_id = start_resp.json()["job_id"]
# Poll for completion
import time
while True:
status = requests.get(f"{BASE_URL}/db/cluster_iib_output_job_status",
params={"job_id": job_id}).json()
if status.get("status") == "completed":
clusters = status["result"]["clusters"]
for c in clusters:
print(f"Topic: {c['title']}, Count: {c['size']}")
print(f" Keywords: {c['keywords']}")
print(f" Files: {c['paths'][:3]}...")
break
time.sleep(2)
```
---
## Common Operations
### Batch Tagging
```python
# Create a tag
tag = requests.post(f"{BASE_URL}/db/add_custom_tag",
json={"tag_name": "favorites"}).json()
# Batch add tag to images
requests.post(f"{BASE_URL}/db/batch_update_image_tag", json={
"img_paths": ["/path/to/img1.png", "/path/to/img2.png"],
"action": "add",
"tag_id": tag["id"]
})
```
### Get Image Generation Parameters
```python
# Single image
geninfo = requests.get(f"{BASE_URL}/image_geninfo",
params={"path": "/path/to/image.png"}).text
# Batch get
batch_info = requests.post(f"{BASE_URL}/image_geninfo_batch", json={
"paths": ["/path/to/img1.png", "/path/to/img2.png"]
}).json()
```
### Smart File Organization
```python
# Start organization job
job = requests.post(f"{BASE_URL}/db/organize_files_start", json={
"folder_paths": ["/messy/folder"],
"dest_folder": "/organized/folder",
"threshold": 0.85,
"lang": "en"
}).json()
# Wait for completion then confirm
requests.post(f"{BASE_URL}/db/organize_files_confirm", json={
"job_id": job["job_id"]
})
```
---
## Reference Documentation
See detailed API documentation: [references/api-reference.md](references/api-reference.md)

252
skills/iib/SKILL.md Normal file
View File

@ -0,0 +1,252 @@
---
name: iib
description: Interact with IIB (Infinite Image Browsing) service for searching, browsing, tagging, and organizing AI-generated images. Use when the user needs to search images by prompt/keyword, manage image tags, organize files into folders, get image generation parameters, or work with an image library.
---
# IIB (Infinite Image Browsing)
IIB is an image/video browsing and management tool that parses metadata from AI generation tools (Stable Diffusion, ComfyUI, etc.).
## Before You Start
**IMPORTANT:** Always do these two things first:
1. **Ask the user for the port** if they started the service themselves (common ports: `7866` standalone, `7860` SD WebUI extension)
2. **Test connectivity** with a hello request before any other operation
```bash
curl --noproxy "*" -s http://127.0.0.1:<PORT>/infinite_image_browsing/hello
# Returns: "hello" if service is running
```
Note: Use `--noproxy "*"` to bypass proxy for localhost connections.
**If service is not running**, start it:
```bash
cd /path/to/sd-webui-infinite-image-browsing
python app.py --port 7866
```
To run as a background daemon:
```bash
nohup python app.py --port 7866 > iib.log 2>&1 &
```
## Quick Reference
| Task | Method | Endpoint |
|------|--------|----------|
| Search images | POST | `/db/search_by_substr` |
| Search by tags | POST | `/db/match_images_by_tags` |
| Random images | GET | `/db/random_images` |
| List folder | GET | `/files?folder_path=...` |
| Move files | POST | `/move_files` |
| Copy files | POST | `/copy_files` |
| Tag images | POST | `/db/batch_update_image_tag` |
| Get image metadata | GET | `/image_geninfo?path=...` |
| Add library path | POST | `/db/extra_paths` |
| Remove library path | DELETE | `/db/extra_paths` |
Base URL: `http://127.0.0.1:7866/infinite_image_browsing`
## Core Operations
### Search Images
Search by keyword in file path or generation parameters:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "landscape", "cursor": "", "size": 50}'
```
Search with regex pattern:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "", "regexp": "masterpiece.*1girl", "cursor": "", "size": 50}'
```
Limit to specific folders:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "portrait", "folder_paths": ["/path/to/folder"], "cursor": "", "size": 50}'
```
Response:
```json
{
"files": [{"fullpath": "/path/to/image.png", "name": "image.png", "size": "1.2 MB", ...}],
"cursor": {"has_next": true, "next": "cursor_string"}
}
```
### Tag Management
Get all tags:
```bash
curl http://127.0.0.1:7866/infinite_image_browsing/db/basic_info
# Response includes: {"tags": [{"id": 1, "name": "favorites", "type": "custom"}, ...]}
```
Create a tag:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/add_custom_tag \
-H "Content-Type: application/json" \
-d '{"tag_name": "favorites"}'
```
Tag multiple images:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/batch_update_image_tag \
-H "Content-Type: application/json" \
-d '{"img_paths": ["/path/to/img1.png", "/path/to/img2.png"], "action": "add", "tag_id": 1}'
```
Search by tags (AND/OR/NOT logic):
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/match_images_by_tags \
-H "Content-Type: application/json" \
-d '{"and_tags": [1], "or_tags": [], "not_tags": [2], "cursor": "", "size": 50}'
```
### File Operations
List folder contents:
```bash
curl "http://127.0.0.1:7866/infinite_image_browsing/files?folder_path=/path/to/images"
```
Move files:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/move_files \
-H "Content-Type: application/json" \
-d '{"file_paths": ["/path/to/img1.png"], "dest": "/new/folder", "create_dest_folder": true}'
```
Copy files:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/copy_files \
-H "Content-Type: application/json" \
-d '{"file_paths": ["/path/to/img1.png"], "dest": "/backup/folder", "create_dest_folder": true}'
```
Delete files:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/delete_files \
-H "Content-Type: application/json" \
-d '{"file_paths": ["/path/to/unwanted.png"]}'
```
### Image Metadata
Get generation parameters (prompt, seed, model, etc.):
```bash
curl "http://127.0.0.1:7866/infinite_image_browsing/image_geninfo?path=/path/to/image.png"
```
Batch get metadata:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/image_geninfo_batch \
-H "Content-Type: application/json" \
-d '{"paths": ["/path/to/img1.png", "/path/to/img2.png"]}'
```
### Library Management
List registered paths:
```bash
curl http://127.0.0.1:7866/infinite_image_browsing/db/extra_paths
```
Add a folder to library:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/extra_paths \
-H "Content-Type: application/json" \
-d '{"path": "/new/image/folder", "types": ["scanned"]}'
```
Remove a folder (also cleans up orphaned image records):
```bash
curl -X DELETE http://127.0.0.1:7866/infinite_image_browsing/db/extra_paths \
-H "Content-Type: application/json" \
-d '{"path": "/old/folder", "types": ["scanned"]}'
```
Rebuild index after adding paths:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/rebuild_index
```
Path types:
- `scanned`: Indexed, appears in search results
- `scanned-fixed`: Like scanned, but pinned in UI
- `walk`: Browse only, not indexed
## AI Features
### Smart File Organization
Automatically organize images into themed folders:
```bash
# Start organization job
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_start \
-H "Content-Type: application/json" \
-d '{
"folder_paths": ["/messy/folder"],
"dest_folder": "/organized/folder",
"threshold": 0.85,
"lang": "en",
"action": "move"
}'
# Returns: {"job_id": "uuid"}
# Check status
curl "http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_status?job_id=<job_id>"
# Confirm and execute
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_confirm \
-H "Content-Type: application/json" \
-d '{"job_id": "<job_id>"}'
```
### Image Clustering
Analyze images and group by semantic similarity:
```bash
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/cluster_iib_output_job_start \
-H "Content-Type: application/json" \
-d '{
"folder_paths": ["/path/to/images"],
"threshold": 0.85,
"min_cluster_size": 3,
"lang": "en",
"recursive": true
}'
```
## Reference
See [references/api-reference.md](references/api-reference.md) for complete API documentation.

140
skills/iib/agent-guide.md Normal file
View File

@ -0,0 +1,140 @@
# Agent Guide
Task-oriented patterns for common IIB operations.
## Decision Tree
```
User wants to find images
├── By keyword/prompt text → POST /db/search_by_substr (surstr)
├── By regex pattern → POST /db/search_by_substr (regexp)
├── By tag → POST /db/match_images_by_tags
└── Random selection → GET /db/random_images
User wants to organize images
├── Move specific files → POST /move_files
├── Copy specific files → POST /copy_files
├── Auto-organize by theme → POST /db/organize_files_start
└── Delete files → POST /delete_files
User wants image info
├── Generation params → GET /image_geninfo
├── Batch metadata → POST /image_geninfo_batch
└── File listing → GET /files
User wants to manage tags
├── List all tags → GET /db/basic_info
├── Create tag → POST /db/add_custom_tag
├── Apply tag to images → POST /db/batch_update_image_tag
└── Search by tag → POST /db/match_images_by_tags
User wants to manage library
├── List paths → GET /db/extra_paths
├── Add folder → POST /db/extra_paths
├── Remove folder → DELETE /db/extra_paths
└── Rebuild index → POST /db/rebuild_index
```
## Common Workflows
### Find and tag images
```bash
# 1. Search for images
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "sunset", "cursor": "", "size": 100}'
# Note the fullpath values from response
# 2. Check existing tags
curl http://127.0.0.1:7866/infinite_image_browsing/db/basic_info
# Note tag IDs, or create new tag:
# 3. Create tag if needed
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/add_custom_tag \
-H "Content-Type: application/json" \
-d '{"tag_name": "sunset-photos"}'
# Returns: {"id": 5, "name": "sunset-photos", ...}
# 4. Apply tag to found images
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/batch_update_image_tag \
-H "Content-Type: application/json" \
-d '{"img_paths": ["/path/to/img1.png", "/path/to/img2.png"], "action": "add", "tag_id": 5}'
```
### Organize messy folder
```bash
# 1. Start AI organization
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_start \
-H "Content-Type: application/json" \
-d '{
"folder_paths": ["/Downloads/ai-images"],
"dest_folder": "/Pictures/organized",
"threshold": 0.85,
"lang": "en",
"action": "move"
}'
# Returns: {"job_id": "abc123"}
# 2. Poll for completion
curl "http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_status?job_id=abc123"
# Wait until status is "completed"
# 3. Confirm and execute
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/organize_files_confirm \
-H "Content-Type: application/json" \
-d '{"job_id": "abc123"}'
```
### Add new folder to library
```bash
# 1. Add path
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/extra_paths \
-H "Content-Type: application/json" \
-d '{"path": "/new/image/folder", "types": ["scanned"]}'
# 2. Trigger index update
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/update_image_data \
-H "Content-Type: application/json" \
-d '{"path": "/new/image/folder"}'
# 3. Verify images are indexed
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "", "folder_paths": ["/new/image/folder"], "cursor": "", "size": 10}'
```
### Paginate large results
```bash
# First page
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "landscape", "cursor": "", "size": 100}'
# Response: {"files": [...], "cursor": {"has_next": true, "next": "cursor_abc"}}
# Next page
curl -X POST http://127.0.0.1:7866/infinite_image_browsing/db/search_by_substr \
-H "Content-Type: application/json" \
-d '{"surstr": "landscape", "cursor": "cursor_abc", "size": 100}'
# Continue until has_next is false
```
## Error Handling
| Status | Meaning | Action |
|--------|---------|--------|
| 200 | Success | Parse response |
| 400 | Bad request | Check JSON syntax and parameters |
| 404 | Not found | Verify file path exists |
| 500 | Server error | Check IIB logs |
| Connection refused | Service not running | Start IIB service |
## Performance Tips
1. Use `folder_paths` to limit search scope when possible
2. Use batch endpoints (`image_geninfo_batch`, `batch_update_image_tag`) for multiple items
3. Use pagination for large result sets
4. Call `update_image_data` for specific folders instead of full `rebuild_index`